vlakna   otázka

C#

Dobry den, nevim jak vyresit beh programu aby nezatezoval procesor. Mam TCP klienta napsaneho ve vlakne ktery odesle data a ceka na odpoved (pouzivam asynchronni BeginRead() ). Techto vlaken spoustim treba 10.

vlakno1
{
  pripojSekTCP();

  while(true)
  {
    if(!blokace)
    {
      posliDataNaTcp()
      timeoutTimer.Start()
      blokace = true;
    }
  }

  event newData
  {
    zpracujData();
    blokace = false
  }

  event timeout
  {
    blokace = false
  }
}

De mi o to ze v okaziku kdy cekam na nove data zbytecne vytezuju vlakno. Jednou by me to nevadilo ale ja se takto potrebuju pripojit k 10 TCP serverum. Nevim zda jsem problem popsal srozumitelne. pokud ano prosim o radu. Dekuji za radu Tom

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Co je to za pseudo kód? Pošlete raději přímo C# kód.

Jinak pokud použijete BeginRead, nemusíte na nic čekat. Callback se zavolá sám ve chvíli, když přijdou data nebo se spojení uzavře.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Nevím jak ten kód přenést sem. Musim z nej udelat vytazek.

De mi o to, že založím vlákno a v něm se připojím k TCP serveru. Odešlu data a čekám na odpověď. Až přijde tak ji zpracuju a odesílám znova. Po odeslani dat potřebuju to vlákno nějak udržet při živote abych zachytil CallBack, ale aby nevytěžovalo procesor, ted to resim smyckou while.

Jo možná je důležité že je to konzolová aplikace.

Zkusím ještě vypreparovat pointu mého programu a dát ho sem. Jednoduché aplikace zvládám, ale ve vláknech jsem začátečník. Dík za radu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Problém je presne v tom cykle While. Použite metódy s Begin... a End..., tak ako v tomto článku: http://vbnet.cz/clanek--27-kreslici_tabu...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

po spusteni programu vytvorim tento objekt ktery se stara o komunikaci s jednim TCP serverem.

class komunikace
    {
        TcpClient tcpClient;
        NetworkStream networkStream;
        byte[] receiveBuffer;
        byte[] messageToSend = new byte[12] { 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0xFF, 0x03, 0x9c, 0x41, 0x00, 0x01 };
        bool connected;
        bool blokace;

        /// <summary>
        /// konstruktor
        /// </summary>
        public komunikace()
        {
            tcpClient = new TcpClient();
            tcpClient.BeginConnect("192.168.55.128", 502, new AsyncCallback(Connect), null);
            receiveBuffer = new byte[1024];
            //smycka ktera drzi pri zivote vlakno a chtel bych ji vyresit jinak
            while (true)
            {
                if (connected)
                {
                    if (!blokace)
                    {
                        networkStream.Write(messageToSend, 0, 12);
                        blokace = true;
                    } 
                }
            }
        }
        
        private void Connect(IAsyncResult at)
        {
            tcpClient.EndConnect(at);
            networkStream = tcpClient.GetStream();
            connected = true;
            networkStream.BeginRead(receiveBuffer, 0, 1024, new AsyncCallback(ReadData), null);
        }

        /// <summary>
        /// cteni dat
        /// </summary>
        /// <param name="at"></param>
        private void ReadData(IAsyncResult at)
        {
            int receive = networkStream.EndRead(at);
            if (!networkStream.DataAvailable)
            {
                //zpracovani dat, odblokovani odeslani
                blokace = false;
            }
            networkStream.BeginRead(receiveBuffer, 0, 1024, new AsyncCallback(ReadData), null);
        }

    }

pokud techto objektu vytvorim vic a to co je v konstruktoru spustim v samostatnych vlaknech tak me ty while cykli moc zatezuji procesor a pritom nic nedelaji.

Myslenka proc to takto delam byla aby kazde TCP spojeni mohlo bezet nezavisle a nebylo brzdeno pri odesilani a prijmu ostatnich v pripade ze by komunikace byla jen v hlavnim vlaknu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zamyslite sa nad tým, čo robí cyklus While. Tento cyklus neustále vyhodnocuje danú podmienku, čím zaťažuje procesor. Presne kvôli tomu sú tie páry metód Begin... a End..., ktoré procesor nezaťažujú. Je to vysvetlené v tom článku.

Nie je zlé používať na to vlákna, len sa vyhnite cyklu While, namiesto neho BeginRead...EndRead; BeginWrite...EndWrite, atď.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tomu rozumim zbavit se toho cyklu while ale jak :) chtel jsem aby kazde TCP spojeni melo svoje vlakno.

Ale to je asi zbytecne. Zalozim vsechny spojeni v hlavnim vlaknu programu.

Mam jen jeste jeden dotaz. Ze BeginRead ceka na prichozi data a neblokuje vlakno to vim. Ale v pripade ze data prijdou, nastane CallBack a spusti se metoda ReadData. Blokuje metoda ReadData hlavni vlakno nebo se spusti ve vlastnim?

private void ReadData(IAsyncResult at)
        {
            int receive = networkStream.EndRead(at);
            if (!networkStream.DataAvailable)
            {
                //zpracovani dat            }
            networkStream.BeginRead(receiveBuffer, 0, 1024, new AsyncCallback(ReadData), null);
}

Dik

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Doporučuji si nejdřív přečíst něco o vícevláknovém programování a synchronizací.

V dotazu vidím zmatení - používate asynchronní metody pro synchronní zpracování. To je od základu špatně. Proč něco volat asynchronně, když na to stejně chcete v aktuálním vlákně čekat? Další problém je samozřejmě čekání smyčkou. Tím vytížíte procesor. Nastadujte si například ManualResetEventSlim, kterým můžete v jednom vlákně čekat na událost z druhé bez zatížení procesoru.

Dále tam vidím problém s proměnnou blokace. Teoreticky se může vynechat jedno odeslání dat, pokud přijmete rychle za sebou data a odesílací smyčka mezitím blokaci nastaví na true. Opět je potřeba se naučit vícevláknovou synchronizaci.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback