10

我正在实现一个需要实现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 库中是否已有实现?

4

4 回答 4

6

这有点快速和肮脏,但您可以实现一个实现 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);
于 2011-02-18T04:08:22.290 回答
6

快速破解方法是使用委托:

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

这种方法的缺点是,如果两个线程同时调用这个方法,你需要小心,你会得到一个错误。

于 2011-02-18T04:14:31.100 回答
1

我不确定我是否遗漏了什么,但今天你可以返回Task.CompletedTask/ Task.FromResultTask工具IAsyncResult

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

IAsyncResult.IsCompleted是正确true的。该Func.BeginInvoke方法不会导致 true。

于 2020-07-15T01:32:32.530 回答
0

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

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;
}
于 2020-10-20T21:22:07.467 回答