2012-02-13 96 views
2

去年,我编写了一个具有经典同步和异步方法的Web API库。我现在尝试使用新的C#异步CTP 3添加TaskAsync方法。使用异步CTP封装同步方法不起作用

我写了这个简单的代码来封装同步方法:

partial class Client : IClient { 
    public string Authenticate(string username, string password) 
    { 
     // long synchronous code here 
    } 
    public Task<string> AuthenticateTaskAsync(string username, string password) { 
     var p = new { username = username, password = password }; 
     var task = new Task<string>(p1 => this.Authenticate(p.username, p.password), p); 
     return task; 
    } 
} 

然后,从我的WPF 4应用程序,我有一个异步方法使用它:

public class LoginViewModel { 
    private IClient client; 

    // called by an ICommand 
    private async Task DoLogin(string username, string password) { 
     UpdateStatus("Authenticating...", true); 
     try { 
      var result = await client.AuthenticateTaskAsync(username, password); 
      // do stuff with result 
      UpdateStatus("Authenticated. Fetching User informations...", true); 
     } catch (Exception ex) { 
      UpdateStatus("Authentication error.", ex, false); 
     } 
    } 
} 

的问题是:我的同步方法永远不会被调用。调试器进入result = await client.AuthenticateTaskAsync(username, password);,调试器继续工作,不再回来。同步内网中的断点会中断。 UpdateStatus永远不会被调用。很奇怪(我虽然是一个调试器的实现问题)。

然后我看了WebClient.DownloadStringTaskAsync是如何实现的。我将我的API客户端方法更改为:

partial class Client : IClient { 
    public Task<string> AuthenticateTaskAsync(string username, string password) { 
     var tcs = new TaskCompletionSource<string>(); 

     try { 
      tcs.TrySetResult(this.Authenticate(username, password)); 
     } catch (Exception ex) { 
      tcs.TrySetException(ex); 
     } 

     return tcs.Task; 
    } 
} 

现在它工作。有人可以解释为什么第一个代码不起作用吗?

回答

4

你是创建的任务,但从来没有开始它。它被创建为“冷” - 在提供给构造函数的函数实际被调用之前,它需要启动它。

要么调用Task.Start(),或使用TaskEx.Run()Task.Factory.StartNew(),而不是调用Task构造:

public Task<string> AuthenticateTaskAsync(string username, string password) { 
    return TaskEx.Run(() => this.Authenticate(username, password)); 
} 

注意,没有必要为匿名类型在这里 - 只是让编译器捕获的参数。

+0

哦......是的,我失败了很多。谢谢 :) – SandRock 2012-02-13 13:26:52