c#async等待和异常

时间:2017-02-06 10:40:14

标签: c# exception asynchronous async-await

我写了一个visual studio 2015 c#程序,用于从自定义以太网设备读取一些数据。我需要使用异步等待指令,因为数据将在预定的时间内一起读取。

我使用自定义.NET库来读取数据;这是我的代码:

private void timerPollingData_Tick(object sender, EventArgs e)
{
   readDevice_01();
   readDevice_02();
   // and so on for all devices ...
}

private async void readDevice_01()
{
   var result = await getDataDevice_01();
   // Save data
}

private async void readDevice_02()
{
   var result = await getDataDevice_02();
   // Save data
}

private Task<string> getDataDevice_01()
{
   MyCustomLibrary readDevice = new MyCustomLibrary.Master();
   return Task.Factory.StartNew(() => readDevice.ReadHoldingRegister(... some parameters ...).ToString());                       
}

private Task<string> getDataDevice_02()
{
   MyCustomLibrary readDevice = new MyCustomLibrary.Master();
   return Task.Factory.StartNew(() => readDevice.ReadHoldingRegister(... some parameters ...).ToString());                       
}

我怀疑: 处理每个任务异常的最佳做法是什么?我需要了解哪些设备从以太网拔出或关闭,然后停止用于从中检索数据的任务。

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

你应该避免async void;将async Task用于除异步事件处理程序之外的所有内容。有关详细信息,请参阅我在async best practices上的文章。

另外,你不应该使用StartNew;它是一个低级别,非常危险的API,具有不适当的默认参数值。使用Task.Run代替StartNew。有关详细信息,请参阅StartNew is dangerous上的博文。

  

我需要使用异步等待指令,因为数据将在预定的时间内一起读取。

Asynchrony是一种并发形式,您可以使用Task.Run ,如果您的设备API没有异步方法:

private async void timerPollingData_Tick(object sender, EventArgs e)
{
  var task1 = readDevice_01();
  var task2 = readDevice_02();
  // and so on for all devices ...
  await Task.WhenAll(task1, task2, ...);
}

private async Task readDevice_01()
{
  var result = await Task.Run(() => getDataDevice_01());
  // Save data
}

private string getDataDevice_01()
{
  MyCustomLibrary readDevice = new MyCustomLibrary.Master();
  return readDevice.ReadHoldingRegister(... some parameters ...).ToString();                       
}

如果您的API采用ReadHoldingRegisterAsync方法,则可以更自然地表达为:

private async void timerPollingData_Tick(object sender, EventArgs e)
{
  var task1 = readDevice_01Async();
  var task2 = readDevice_02Async();
  // and so on for all devices ...
  await Task.WhenAll(task1, task2, ...);
}

private async Task readDevice_01Async()
{
  var result = await getDataDevice_01Async();
  // Save data
}

private async Task<string> getDataDevice_01Async()
{
  MyCustomLibrary readDevice = new MyCustomLibrary.Master();
  var result = await readDevice.ReadHoldingRegisterAsync(... some parameters ...);
  return result.ToString();
}
  

我怀疑:处理每个任务异常的最佳做法是什么?我需要了解哪些设备从以太网拔出或关闭,然后停止用于从中检索数据的任务。

从任务中获取例外的最佳做法是await

在提出异常后,您不必担心停止任务。当任务报告其异常时,它已经停止。