2013-12-19 2 views
1

Мне действительно понравилось использовать MVVM и async/await, поэтому, естественно, я взломал проект, чтобы создать новую разработку (MVVM), которая обменивается данными с устройствами по последовательному интерфейсу, и пользовательский интерфейс будет реагировать. Мои классы-драйверы - это синхронные вызовы, которые взаимодействуют с устройством по последовательному каналу и могут занимать время (хотя, как правило, нет) в зависимости от того, сколько данных возвращается, если я получаю соответствующий возврат или если драйвер должен продолжать ждать еще несколько секунд чтобы узнать, подходит ли соответствующая доходность и т. д.Task.Run Serial Communications

В любом случае, что я закончил делать, это обматывание сообщений в ожидании Task.Run (() => {}); обертка. Таким образом, с точки зрения моего пользовательского интерфейса, когда пользователь нажимает кнопку, волшебным образом ее бросают в пул потоков, и мой пользовательский интерфейс остается отзывчивым при обработке задачи.

Является ли приведенная ниже реализация неправильной? Поскольку я общаюсь с Serial, это не моя работа, технически связанная с I/O работа вместо работы с привязкой к ЦП (Task.Run предположительно используется только для работы с ЦП, из того, что я прочитал)? Ниже метод вызывается в моей модели представления, выполнив:

var returnVal = await _objName.InitAsync(); 

Тогда вызов Task.Run ....

public async Task<bool> InitAsync() 
    { 
     bool returnVal = false; 

     await Task.Run(() => 
     { 
      System.Threading.Thread.Sleep(COMMAND_DELAY_MILLISECONDS); 
      returnVal = _obj.InitiateProvision(); 
     }); 

     return returnVal; 
    } 

Возвращаемое значение BOOL просто говорится, если команда была успешной или нет. Код работает очень хорошо, поскольку я тестировал его уже около месяца без каких-либо проблем, но я не уверен, что это лучше ... Есть ли «лучший» способ сделать это, хотя он все еще может поддерживать асинхронные операции? Любое руководство ценится!

+0

Какая точка сна перед тем, как вы вызовете 'InitiateProvision'? Также является ли «InitiateProvision» медленным? –

+0

Чтобы добавить короткую задержку перед отправкой команды, у меня есть около 3 команд, которые я вызываю последовательно так, поэтому я добавил это, чтобы дать некоторое время между вызовами. Я не уверен, что это лучше всего ... работа с последовательными портами для меня довольно нова. – YnotDraw

+0

Возможно, вы вернули возвращаемое значение _obj.InitiateProvision из Task.Run, тем самым избегая захвата локальной переменной returnVal, избегая создания типов и экземпляров. –

ответ

1

Если вы используете Task.Run, просто чтобы у вас была задержка до того, как вы сделаете свою команду, просто используйте delay и не свяжите threadpool.

public async Task<bool> InitAsync() 
{ 
    bool returnVal = false; 

    await Task.Delay(COMMAND_DELAY_MILLISECONDS).ConfigureAwait(false); 
    returnVal = _obj.InitiateProvision(); 

    return returnVal; 
} 

Вы сказали, что было 3 команды, вы можете просто сделать все три команды подряд, если она подходит для вашего дизайна, вы можете иметь более одного await в функции.

public async Task<bool> InitAsync() 
{ 
    bool returnVal = false; 

    await Task.Delay(COMMAND_DELAY_MILLISECONDS).ConfigureAwait(false); 
    returnVal = _obj.InitiateProvision(); 

    if(returnVal == true) 
    { 
     await Task.Delay(COMMAND_DELAY_MILLISECONDS).ConfigureAwait(false); 
     returnVal = _obj.CommandTwo(); 
    } 

    if(returnVal == true) 
    { 
     await Task.Delay(COMMAND_DELAY_MILLISECONDS).ConfigureAwait(false); 
     returnVal = _obj.CommandThree(); 
    } 

    return returnVal; 
} 

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

+0

Я только что видел ваш обновленный комментарий - вызов InitiateProvision медленный, и это то, что связывает интерфейс. Задержка используется только для того, чтобы разрешить некоторую подушку между вызовами - я обязательно добавлю Task.Delay, но все равно ОК, чтобы обернуть вызов InitiateProvision в Task.Run. – YnotDraw

+0

Хорошо, фантастика! Итак, «ожидайте Task.Delay» за задержки и завершите медленный вызов InitiateProvision и т. Д. В «Ожидание Task.Run»? – YnotDraw

+2

Я бы по-прежнему пытался избежать использования 'Task.Run' в вашей функции. Вместо этого вы все равно можете использовать 'async' и выполнять' 'ждут Task.Delay', но вместо того, чтобы' Task.Run' в этой функции «ждать Task.Run (() => InitAsync());' поэтому у вас есть *** caller *** завершает функцию в Task.Run. –

Смежные вопросы