如何处理从 .Net 外部调用的库中的 async/await 用法?

How to handle async/await usage in a library called from outside .Net?

我是 C# 这个领域的新手,坦率地说,我正在努力理解范例。看来我不是一个人(, http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html)

在我的例子中,我在 C# 库中编写一个小型 TCP 服务器,本质上,TCP 服务器应该 运行 在它自己的线程中,并且 post 数据通过提供的回调返回到应用程序.所以我们可能有一个进入库的入口点:

class MyServer
{
 void StartServerRunningAsync(Callback callback)
 {
  this.callback = callback; //calls back into unmanaged via 'magic' COM interop each time a TCP client posts interesting data
  StartRunningThread(); //this creates a thread to run the server and returns 
 }
 void StartRunningThread()
 {
  new Thread(new ThreadStart(Run)).Start();
 }
 void Run()
 {
  //do standard TCP async stuff treating `Run` like a local `Main`
 }
}

该库将在非托管 C++ 应用程序(在本例中特别是通过 COM)中使用,该应用程序 运行 是后台服务器。所以我不认为 StartServerRunning can/should 是 async 但这意味着我 stuck/confused 如何使用 async/await所有这些都是因为它会根据上面的链接在您的整个堆栈中传播。

这真的是个问题还是我误解了一些基本的东西? TPL怎么可以这样封装?

实际上,使用 async/await 让事情变得更容易。

class MyServer
{
 // notice async void here instead of async Task
 async void StartServerRunning(Callback callback)
  {
   await StartRunningThreadAsync(); // start server asynchronously
   callback();
  }
}

从外部观察者的角度来看,StartServerRunning在遇到第一个等待时立即退出。但是在后台,方法还是"running"。一旦 StartRunningThreadAsync 完成,就会调用 callback。当在 C# 代码中使用时,这不是一个好的做法,但当涉及 C 互操作时,我不认为这是一件坏事。

我还建议实现异常处理,这样任何异常都不会超出此方法。喜欢:

class MyServer
{
 async void StartServerRunning(Callback callback)
  {
   bool wasError = false;
   try{
     await StartRunningThreadAsync(); // start server asynchronously
   }catch(Exception ex)
   {
     // log exception
     wasError = true;
   }
   callback(wasError);
  }
}