Отмена фонового работника, который постоянно читает из сетевого потока - PullRequest
0 голосов
/ 15 февраля 2012

У меня работает TCP-сервер, который регулярно выдает сообщения размером 2 байта.

Я пытаюсь создать клиентскую форму, которая подключается к серверу и непрерывно читает из потока, пока я не нажмукнопка отключения в форме.

Пока клиент работает нормально, за исключением того, что я не могу отключиться.Я установил для CancellationPending значение true, но, похоже, он сбрасывается обратно в false, прежде чем метод dowork получит возможность установить e.Cancel.

Я также уверен, что должен быть более приемлемый способ непрерывного чтения потокаи запись в форму - в данный момент я вызываю RunWorkerAsync в методе Worker Completed для выполнения цикла!

    private void Disconnect()
    {
        commsWorker1.CancelAsync();
    }

    private void ReadFromStream()
    {
        try
        {
            commsWorker1.RunWorkerAsync();
        }
        catch (Exception ex)
        {
            writeToBox("Error: " + ex.Message);
        }
    }

    //background worker dowork method
    private void BackGroundGetServerData(object sender, DoWorkEventArgs e)
    {
        if (true == commsWorker1.CancellationPending)
        {
            e.Cancel = true;
        }
        else
        {
            Byte[] dataArray = new Byte[2];
            try
            {
                _DataStream.Read(dataArray, 0, 2);
                String reply = System.Text.Encoding.ASCII.GetString(dataArray);
                e.Result = reply;
            }
            catch (Exception ex)
            {
            }
        }
    }

    //background worker workercompleted method
    private void BackGroundDisplayMessages(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            //close connection here
        }
        else
        {
            writeToBox((String)e.Result);
            commsWorker1.RunWorkerAsync();
        }

    }
}

}

Ответы [ 2 ]

0 голосов
/ 15 февраля 2012

Похоже, что вы вызываете RunWorkerAsync () в методе worker complete, и это сбрасывает вашу опцию CancellationPending. Я думаю, что вы можете попытаться исправить это, добавив в метод Disconnect () несколько disconnectFlag = true; а в методе WorkerComplete вы должны добавить:

if (e.Cancelled || disconnectFlag)
    {
        disconnectFlag = false;
        //close connection here
    } else ...
0 голосов
/ 15 февраля 2012

Разве вы не можете просто выполнить цикл внутри метода фонового рабочего?

private void BackGroundGetServerData(object sender, DoWorkEventArgs e)
{
    while(true)
    {
        Byte[] dataArray = new Byte[2];
        try
        {
            _DataStream.Read(dataArray, 0, 2);
            String reply = System.Text.Encoding.ASCII.GetString(dataArray);
            e.Result = reply;
        }
        catch (Exception ex)
        {
            return;
        }
    }
}

Затем при отключении просто закройте розетку. Это приведет к тому, что Exception будет добавлено в цикл while, и вы сможете корректно выйти через блок catch.

Edit: Затем вы можете обновить графический интерфейс из цикла после прочтения каждого сообщения. Убедитесь, что дескриптор обновляемого элемента управления доступен (при условии, что он называется box):

delegate void updateDelegate(String p);

private void BackGroundGetServerData(object sender, DoWorkEventArgs e)
{
    while(true)
    {
        Byte[] dataArray = new Byte[2];
        try
        {
            _DataStream.Read(dataArray, 0, 2);
            String reply = System.Text.Encoding.ASCII.GetString(dataArray);
            box.BeginInvoke(new updateDelegate(writeToBox), reply);
        }
        catch (Exception ex)
        {
            return;
        }
    }
}

BeginInvoke требуется в этом случае, потому что вы пытаетесь обновить графический интерфейс из другого потока, что недопустимо. Этот метод перенаправляет обновление в поток графического интерфейса.

...