如何创建立即完成的IAsyncResult?

时间:2011-02-18 03:50:41

标签: c# .net asynchronous delegates iasyncresult

我正在实现一个需要BeginDoSomethingEndDoSomething方法实现的接口。但是我的DoSomething并没有真正长期运行。 为简单起见,假设DoSomething仅比较两个变量并返回> B'/ P>

所以我的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库中是否已有实现?

4 个答案:

答案 0 :(得分:5)

这有点快,很脏,但您可以实现一个实现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);

答案 1 :(得分:5)

快速入侵的方法是使用委托:

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);
}

这种方法的缺点是,如果两个线程同时调用此方法,则需要小心,否则会出错。

答案 2 :(得分:0)

我不确定是否丢失了某些内容,但是今天您可以返回Task.CompletedTask / Task.FromResultTask实现IAsyncResult

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

IAsyncResult.IsCompleted在这里正确trueFunc.BeginInvoke方法不会得出正确的结果。

答案 3 :(得分:0)

我建议您遵循指示here,以便能够使用基于任务的方法创建实现,以防其中之一确实运行很长时间。如果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;
}