Разработка механизма асинхронного вызова c # - PullRequest
3 голосов
/ 11 мая 2011

Требуется непрерывно считывать данные с аппаратного обеспечения и отправлять данные на верхние слои для дальнейшей обработки.

В настоящее время я использую синхронный механизм. т.е. Запрос -> Ожидание -> Читать ---> Отправить на обработку.

    do
    {

    int ix = iy;
            iy = 0;

            if(ix<1)
            {
                while (((ix = ReadSst(ref sBuffer)) < 1) && bProcessNotEnded == true)
                {
                    if (ix < 0)    // BT Error
                    {
                        eErr = CError.BUFF_KILL; //Throw error and exit
                        break;
                    }

                    Thread.Sleep(2); 

                    iTimeOut += 2;
                    if (iTimeOut > TIMEOUT_2000)
                    {
                        eErr = CError.TIMEOUT_ERR;
                        objLogger.WriteLine("HW TIMED OUT");
                        break;
                    }

                }
            }

            iBytesRead = ix;

            if (iBytesRead <= 0)
            {
                eErr = CError.READ_ERR;
                objLogger.WriteLine("READ ERROR");
                break;
            }

            sReadMsg = sReadMsg + sBuffer;


    if(sReadMsg.Length >0)
        iEndPos = sReadMsg.IndexOf('\n',1);
    else
        iEndPos = -1;


                if (sReadMsg.Length > 2)
                {
                    if ((iEndPos == 0 && sReadMsg[0] == '\n') || (iEndPos > 0 && sReadMsg[sReadMsg.Length - 1] == '\n' && sReadMsg[sReadMsg.Length - 2] == '\r')) //finished
                    {
                        Thread.Sleep(50);  // wait a short time to be sure there that there is no further input
                        if (sReadMsg.Length >= 3 && sReadMsg[sReadMsg.Length - 3] == 'a')
                            continue;

                        iy = ReadSst(ref sBuffer);
                        if (iy == 0)
                        {
                            bProcessNotEnded = false;
                            objLogger.WriteLine("bProcessNotEnded is made false, End of frame detected");
                            break;
                        }
                        else if (iy < 0)
                        {
                            eErr = CError.BUFF_KILL;  // error
                            break;
                        }
                    }
                }


        } while (bProcessNotEnded); 

Метод ReadSst - это вызов оборудования для запроса данных.

Как видно из кода, существующая логика i зацикливается и читается, пока флаг bProcessNotEnded не станет истинным. Как только конец кадра обнаружен в строковом буфере, который я получаю, я устанавливаю флаг в false и цикл останавливается (так же, как чтение с аппаратного обеспечения)

Теперь, когда мне нужно добиться некоторого параллелизма в моем коде для повышения производительности, я хочу научиться улучшать его так, как чтение выполняется асинхронно.

Любой, кто поможет мне улучшить этот существующий дизайн.

Заранее спасибо

Ответы [ 3 ]

2 голосов
/ 11 мая 2011

Как правило, есть три общих шаблона для выполнения асинхронной работы в .NET:

  1. Модель асинхронного программирования
  2. Асинхронный на основе событиймодель программирования
  3. Параллельная библиотека задач (.NET 4.0)

Для вашего явно низкоуровневого фрагмента кода я бы выбрал 1 или3, как 2 обычно используется на компонентах более высокого уровня.

Общий дизайн, который нужно выполнить, заключался бы в том, чтобы выполнить ваш цикл в отдельном потоке, используя любой из вышеперечисленных способов, и когда цикл завершится, уведомив вызывающий поток, чтооперация завершена, и результат (в вашем случае это должно быть содержимое sReadMsg) соответствующим образом (зависит от того, какой путь вы выберете).

Вот краткий пример того, как легко вы могли бысделать это с помощью TPL:

private void ReadMessageAsync()
{
    // Set up the task to read the message from the hardware device.
    Task<string> readMessageTask = new Task<string>(ReadMessage);

    // Set up the task to process the message when the message was read from the device.
    readMessageTask.ContinueWith(ProcessMessage);

    // Start the task asynchronously.
    readMessageTask.Start();
}

private void ProcessMessage(Task<string> readMessageTask)
{
    string message = readMessageTask.Result;

    // Process the message
}

private string ReadMessage()
{
    string message = string.Empty;

    // Retrieve the message using your loop

    return message;
}
1 голос
/ 11 мая 2011

Я думаю, что ваш дизайн может быть улучшен с помощью асинхронного ввода-вывода. Мы не видели, как был реализован ReadSst, но я подозреваю, что вы где-то там используете Stream. Вместо вызова Read (который является синхронным) вы должны использовать BeginRead (который является асинхронным). Это изменение приведет к другим более значительным изменениям в дизайне кода. Я бы начал с исследования асинхронного ввода-вывода и попытался бы реализовать его самостоятельно, а затем опубликовать последующие вопросы, если это более конкретные проблемы, с которыми мы можем помочь.

0 голосов
/ 11 мая 2011

Существует компонент .net, который называется Фоновый рабочий, вы можете поместить обработку цикла в событие 'DoWork' и одновременно поддерживать отзывчивость вашего приложения.

Вот класс, который выставляет его:

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker%28v=VS.90%29.aspx

Также содержит хороший пример того, как его использовать.

Надеюсь, это поможет

...