我如何使用AsyncCTP与TFS APM方法(Query.Begin / EndQuery)? [英] How can I use the AsyncCTP with an TFS APM Method (Query.Begin/EndQuery)?

查看:341
本文介绍了我如何使用AsyncCTP与TFS APM方法(Query.Begin / EndQuery)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想使用AsyncCTP TFS的尝试。目前有一个上一个TFS查询实例调用RunQuery长时间运行的方法。

Would like to try using AsyncCTP with TFS. Currently have a long running method that calls RunQuery on a TFS Query instance.

查询公开的APM方法BeginQuery()和EndQuery()。据我了解,建议的方法来包装这些使用AsyncCTP是这样的:(例如,从文档)

Query exposes the APM methods BeginQuery() and EndQuery(). As I understand it, the recommended approach to wrap these using AsyncCTP is something like: (example from docs)

Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead, buffer, offset, count, null);

此外,已在扩展方法作为文档包好,所以我实际的方法是这样的:

Further, have wrapped it in an extension method as in the docs so my actual method looks like:

public static Task<WorkItemCollection> RunQueryAsync(this Query query)
{
    if (query== null) 
        throw new ArgumentNullException("Query");

    return Task<WorkItemCollection>.Factory.FromAsync(query.BeginQuery, query.EndQuery, null);
} 

...但是这无法编译。收到无效的参数智能感知错误,坦率地说,我不是很懂,因为类型和格式看起来是正确的。一个可能的问题可能是,查询APM方法期待一个ICanceleableAsyncResult,而任务工厂期待一个IAsyncResult - 但看TFS API,ICanceleableAsyncResult是IAsyncResult的的一个特例。

...but this fails to compile. Getting an "invalid argument" intellisense error that, frankly, I can't really understand because the types and format look correct. One possible issue might be that the Query APM methods expect an ICanceleableAsyncResult whereas the Task factory is expecting an IAsyncResult -- but looking at the TFS API, ICanceleableAsyncResult is a specialization of IAsyncResult.

不知道我是否做错了或它是不可能的。很想能够做到这一点的AsyncCTP方式,但可能要回到APM模式 - !唉

Not sure whether i'm doing it wrong or its just not possible. Would love to be able to do it the AsyncCTP way but may have to go back to the APM pattern -- ugh!

推荐答案

更新:我的 Nito.AsyncEx 库现在包括 TeamFoundationClientAsyncFactory 类型,它可以用来代替下方滚动您自己的实现。

Update: My Nito.AsyncEx library now includes a TeamFoundationClientAsyncFactory type, which can be used instead of rolling your own implementation below.

TFS的API不严格遵循APM模式,因为它并不需要一个状态参数,这是preventing内置 TaskFactory.FromAsync 无法正常工作。

The TFS API is not strictly following the APM pattern because it does not take a state parameter, and this is preventing the built-in TaskFactory.FromAsync from working.

您必须写自己的 FromAsync 等同,这是可以做到用 TaskCompletionSource

You'll have to write your own FromAsync equivalent, which can be done using TaskCompletionSource:

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Client;

public static class TfsUtils<TResult>
{
  public static Task<TResult> FromTfsApm(Func<AsyncCallback, ICancelableAsyncResult> beginMethod, Func<ICancelableAsyncResult, TResult> endMethod, CancellationToken token)
  {
    // Represent the asynchronous operation by a manually-controlled task.
    TaskCompletionSource<TResult> tcs = new TaskCompletionSource<TResult>();
    try
    {
      // Begin the TFS asynchronous operation.
      var asyncResult = beginMethod(Callback(endMethod, tcs));

      // If our CancellationToken is signalled, cancel the TFS operation.
      token.Register(asyncResult.Cancel, false);
    }
    catch (Exception ex)
    {
      // If there is any error starting the TFS operation, pass it to the task.
      tcs.TrySetException(ex);
    }

    // Return the manually-controlled task.
    return tcs.Task;
  }

  private static AsyncCallback Callback(Func<ICancelableAsyncResult, TResult> endMethod, TaskCompletionSource<TResult> tcs)
  {
    // This delegate will be invoked when the TFS operation completes.
    return asyncResult =>
    {
      var cancelableAsyncResult = (ICancelableAsyncResult)asyncResult;

      // First check if we were canceled, and cancel our task if we were.
      if (cancelableAsyncResult.IsCanceled)
        tcs.TrySetCanceled();
      else
      {
        try
        {
          // Call the TFS End* method to get the result, and place it in the task.
          tcs.TrySetResult(endMethod(cancelableAsyncResult));
        }
        catch (Exception ex)
        {
          // Place the TFS operation error in the task.
          tcs.TrySetException(ex);
        }
      }
    };
  }
}

您可以使用它在扩展方法这样:

You can then use it in extension methods as such:

using System.Threading;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

public static class TfsExtensions
{
  public static Task<WorkItemCollection> QueryAsync(this Query query, CancellationToken token = new CancellationToken())
  {
    return TfsUtils<WorkItemCollection>.FromTfsApm(query.BeginQuery, query.EndQuery, token);
  }
}

这篇关于我如何使用AsyncCTP与TFS APM方法(Query.Begin / EndQuery)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆