繁体   English   中英

如何创建立即完成的 IAsyncResult?

[英]How to create an IAsyncResult that immediately completes?

我正在实现一个需要实现BeginDoSomethingEndDoSomething方法的接口。 然而,我的DoSomething并不是真正的长期运行。 为简单起见,假设DoSomething只比较两个变量并返回是否 a > b

所以我的 BeginDoSomething 应该是这样的:

protected override IAsyncResult BeginDoSomething(int a, int b, AsyncCallback callback, object state)
{
     bool returnValue = a > b;
     return ...; //what should I return here?  
     //The method actually already completed and I don't need to wait for anything
 }

我不知道我应该返回什么。 我只实现BeginDoSomething是因为我必须这样做,而不是因为我的方法是长时间运行的。 我需要实现我自己的IAsyncResult吗? .NET 库中是否已有实现?

这有点快速和肮脏,但您可以实现一个实现 IAsyncResult 的类,如下所示:

    public class MyAsyncResult : IAsyncResult
    {
        bool _result;

        public MyAsyncResult(bool result)
        {
            _result = result;
        }

        public bool IsCompleted
        {
            get { return true; }
        }

        public WaitHandle AsyncWaitHandle
        {
            get { throw new NotImplementedException(); }
        }

        public object AsyncState
        {
            get { return _result; }
        }

        public bool CompletedSynchronously
        {
            get { return true; }
        }
    }

然后在你的 BeginDoSomething 中使用它,如下所示:

    return new MyAsyncResult(a > b);

这样做的快速黑客方法是使用委托:

protected override IAsyncResult BeginDoSomething(int a, int b, AsyncCallback callback, object state)
{
     bool returnValue = a > b;
     Func<int,int,bool> func = (x,y) => x > y;
     return func.BeginInvoke(a,b,callback,state);
}

这种方法的缺点是,如果两个线程将同时调用此方法,您需要小心,您将收到错误消息。

我不确定我是否遗漏了什么,但今天你可以只返回Task.CompletedTask / Task.FromResult Task实现IAsyncResult

protected override IAsyncResult BeginDoSomething(int a, int b, AsyncCallback callback, object state)
{
     return Task.FromResult(a > b);
}

IAsyncResult.IsCompleted是理所当然true在这里。 Func.BeginInvoke方法不会导致 true。

我建议您按照此处的说明使用基于任务的方法创建您的实现,以防其中之一确实需要长时间运行。 如果 DoSomething 运行时间很短,您可以通过从其结果创建一个Task来阻止它

public IAsyncResult BeginDoSomething(int a, int b,
                                        AsyncCallback callback,
                                        object state)
{
   return Task.FromResult(DoSomething(a, b)).AsApm(callback, state);
}

public bool EndDoSomething(IAsyncResult asyncResult)
{
   return ((Task<bool>)asyncResult).Result;
}

bool DoSomething(int a, int b)
{
   return a > b;
}

public static IAsyncResult AsApm<T>(this Task<T> task,
                                    AsyncCallback callback,
                                    object state)
{
    if (task == null)
        throw new ArgumentNullException("task");

    var tcs = new TaskCompletionSource<T>(state);
    task.ContinueWith(t =>
                      {
                         if (t.IsFaulted)
                            tcs.TrySetException(t.Exception.InnerExceptions);
                         else if (t.IsCanceled)
                            tcs.TrySetCanceled();
                         else
                            tcs.TrySetResult(t.Result);

                         if (callback != null)
                            callback(tcs.Task);
                      }, TaskScheduler.Default);
    return tcs.Task;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM