c# - 在 C# 中将回调机制实现为异步/等待模式

标签 c# design-patterns asynchronous callback async-await

如何将以下回调驱动的代码正确转换为异步/等待模式:

public class DeviceWrapper
{
 // external device which provides real time stream of data
 private InternalDevice device = new InternalDevice();
 private List<int> accumulationBuffer = new List<int>();

 public void StartReceiving()
 {
     // the following callback invocations might by synchronized by main
     // UI message pump, particular window message pump
     // or some other way
     device.Synchronization = Synchronization.UI;
     device.DataAvailable += DataAvailableHandler;
     device.ReceivingStoppedOrErrorOccured += StopHandler;
     device.Start();
 }

 private void DataAvailableHandler(object sender, DataEventArgs e)
 {
     // Filter data from e.Data and accumulate to accumulationBuffer field.
     // If certail condition is met, signal pending task (if there is any)
     //as complete return to the awaiting caller accumulationBuffer or perhaps temporary buffer created from accumulationBuffer
     // in order to make it available to the caller.
     // Handle also requested cancellation.
 }

 public Task<byte[]> GetData(CancellationToken token)
 {
     // create task returning data filtered and accumulated in DataAvailableHandler 
 }
}
// usage:
async void Test()
{
 DeviceWrapper w = new DeviceWrapper();
 w.StartReceiving();
 while(true)
 {
  byte[] filteredData = await w.GetData(CancellationToken.Null);
  Use(filteredData);
 }
}

我通过阅读 .NET StreamReader 类源代码寻求解决这个问题的灵感,但这让我更加困惑。

感谢各位专家的建议!

最佳答案

您正在寻找TaskCompletionSource<byte[]> 。这是它的近似值:

public Task<byte[]> GetData(CancellationToken token)
{
      cancellationToken.ThrowIfCancellationRequested;

      var tcs = new TaskCompletionSource<byte[]>();
      DataEventHandler dataHandler = null;
      dataHandler = (o, e) => 
      {
          device.DataAvailable -= dataHandler;
          tcs.SetResult(e.Data);
      }

      StopEventHandler stopHandler = null;
      stopHandler = (os, se) =>
      {
            device.ReceivingStoppedOrErrorOccured -= stopHandler;
            // Assuming stop handler has some sort of error property.
            tcs.SetException(se.Exception);
      }

      device.DataAvailable += dataHandler;
      device.ReceivingStoppedOrErrorOccured += stopHandler;
      device.Start();

      return tcs.Task;
}

关于c# - 在 C# 中将回调机制实现为异步/等待模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31598242/

相关文章:

c# - 加载到 XDocument 时如何解析实体?

c# - 使用 IOC 容器的策略设计模式 - 专门用于 Ninject

Javascript 多个文件上传,一次一个

java - 观察者设计模式的主题是接口(interface)还是父类(super class)?

c++ - pimpl设计模式,成员函数需要放在私有(private)类中

reactjs - React JS - 为什么一个按钮被点击两次?

wpf - 如何在后台线程上执行 WPF 筛选器?

c# - 如何: Define a Self Referenced Type Property with Reflection Emit in c#

c# - 系统.InvalidOperationException : Collection was modified

c# - 如何从列表中删除第一项并保留索引