0

我不确定我是否可以在这里很好地解释它,但让我试一试。下面的代码只是为了展示这个想法,因为我只是在这里输入它而不验证编译器中的所有内容。

我有一个方法(比如 Method1),我正在做两件事。1. 调用 Web 服务方法来执行操作。2. 之后,我轮询同一个 Web 服务对象以等待操作结果可用。

所以基本上如下所示。

public class MyClass   
{   
  Method1()   
  {     
    // call Web service method  

    // code for polling    
  }  
}

然而,这种方法使 Method1 阻塞,直到轮询期间确定的操作结果可用。我想更改它,以便 Method1 的调用者可以在调用 Web 服务方法后立即返回,并且可以在 Web 服务结果可用后以某种方式发出信号。所以我想有一个 AutoResetEvent 对象作为我在轮询期间设置为信号状态的类成员。

public class MyClass   
{   
  public AutoResetEvent autoEvent = new AutoResetEvent(false);
  Method1()   
  {     
    // call Web service method  

  }  

  Method2()   
  {     
    // code for polling    
    // change state of autoEvent to signaled once results are availble

  }  

}

使用这种方法,此 API 的用户只需调用立即返回的 Method1,他们就可以等待 autoEvent 得到信号。问题是在这种情况下谁会调用 Method2?

4

1 回答 1

1

异步代码有几种不同的方法。当今 .NET 中最常见的是利用Tasks。对于一个基本示例,您可以执行以下操作:

Task task = Task.Run(() => DoSomething());
task.ContinueWith(() => DoAfterSomething());

这允许代码在后台线程上执行任务时继续处理。对于所有 lambda 和子方法,这可能看起来有点罗嗦和笨拙,这就是引入 async\await 模式的原因。这看起来像:

Task<int> DoSomethingAsync()
{
    // do something asynchronously..
}

async Task<int> ExampleAsync()
{
   int result = await DoSomethingAsync();
   DoAfterSomething();
   return 42;
}

请注意,DoAfterSomething 可能在与原始调用者不同的线程上被调用。

另一种常用的方法是APM方法。这涉及启动异步线程的两种方法和完成它的另一种方法(通常是 BeginX 和 EndX)。这通常看起来像:

FileStream fStream = /* etc */
byte[] buffer = /* etc */
void ReadFile(FileStream fStream)
{
    var asyncResult = fStream.BeginRead(buffer, 0 , buffer.Length, new AsyncCallback(EndReadCallback), null);
}

void EndReadCallback(IAsyncResult result)
{
    int length = fStream.EndRead(result);
    // continue processing on buffer
}

另一种方法是使用事件触发完成的EAP模型。这个模型在 .NET 框架中用得不多,但它就在那里。它的使用如下:

WebDownload download = /* etc */
download.DownloadComplete += (buffer) => { /* do something with buffer */ };
download.Get("http://foo/img.jpg");

就个人而言,我对我创建的所有内容都使用 async\await,但是如果您在遗留组件中遇到它们,其他方法很高兴知道。如果您需要将 APM 或 EAP 转换为基于任务的,您可以使用Task.Factory.FromAsync或使用TaskCompletionSource轻松完成

于 2014-10-01T03:29:25.863 回答