Разработка механизма асинхронного вызова c#

#c# #multithreading #asynchronous

#c# #многопоточность #асинхронный

Вопрос:

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

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

     do
    {

    int ix = iy;
            iy = 0;

            if(ix<1)
            {
                while (((ix = ReadSst(ref sBuffer)) < 1) amp;amp; 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 amp;amp; sReadMsg[0] == 'n') || (iEndPos > 0 amp;amp; sReadMsg[sReadMsg.Length - 1] == 'n' amp;amp; 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 amp;amp; 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 — это вызов, выполняемый аппаратным обеспечением для запроса данных.

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

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

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

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

Комментарии:

1. Это слишком низкий уровень. Оберните это потоком памяти, и у вас будут операции синхронизации / асинхронности.

2. Здравствуйте, возможно, вы захотите опубликовать это в codereview.stackexchange.com слишком

Ответ №1:

Как правило, существует три распространенных шаблона для выполнения асинхронной работы в .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.Resu<

    // Process the message
}

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

    // Retrieve the message using your loop

    return message;
}
  

Комментарии:

1. Привет, Флориан, я ограничен .NET Framework 2.0, я не могу использовать TPL: (учащийся

Ответ №2:

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

Ответ №3:

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

Вот класс, который предоставляет это:

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=VS.90).aspx

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

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