是否可以同步调用异步调用?

时间:2011-04-04 15:22:09

标签: c# asynchronous delegates

我已经在我正在尝试做的事情之下放置了一些非常基本的代码。我有'DoSomethingAshnc'方法执行异步操作。我希望'DoSomething'方法是一个不接受action参数并返回int的同步方法。

public void DoSomething(Action<int> actionToPerformOnComplete)
    {
        DoSomethingAsync(delegate(int val)
            {
                actionToPerformOnComplete(val);
            });
    }

甚至可以让'DoSomething'返回一个整数,就像方法同步发生一样?

4 个答案:

答案 0 :(得分:6)

您需要在同步方法的最后添加一些内容,告诉它等待另一个调用完成。我假设您的异步方法将有一个事件告诉调用者何时完成。

如果是这样,那么我建议使用像ManualResetEvent这样的东西,在同步线程中等待它,并在异步事件的Finish事件接收器中设置它。

示例:

public void DoSomething(Action<int> actionToPerformOnComplete)
{
   ManualResetEvent mre = new ManualResetEvent(false);
   DoSomethingAsync(delegate(int val)
   {
      try
      {
         actionToPerformOnComplete(val);
      }
      finally
      {
         mre.Set();
      }
   });
   mre.WaitOne();
}

答案 1 :(得分:1)

是。你所要做的就是把这行代码放在一边:

IAsyncResult asycn = ... // make a call to Async and get back IAsyncResult 
while(!asycn.IsCompleted)
{
   Thread.Sleep( ....);
}

更新

正如有人问的那样,正确设计的异步操作将实现async pattern MSDN:

  

使用的异步操作   IAsyncResult设计模式是   实现为两个名为的方法   BeginOperationName和   EndOperationName开始和结束   异步操作   OperationName分别为。对于   例如,FileStream类提供   BeginRead和EndRead方法   从文件中异步读取字节。   这些方法实现了   Read的异步版本   方法

答案 2 :(得分:1)

正如其他人所提到的,您需要等待异步方法完成。要在不将Action参数传递给方法的情况下执行此操作,请使用以下代码:

public int DoSomething()
{
   int result;
   ManualResetEvent mre = new ManualResetEvent(false);
   DoSomethingAsync(val => {result = val; mre.Set(); });
   mre.WaitOne();
   return result;
}

执行异步方法,等待它完成并将结果分配给局部变量。返回此结果。

答案 3 :(得分:0)

using System;
using System.Threading;

namespace qqq
{
    class Program
    {
        public static void DoAsync(Action<int> whenDone)
        {
            new Thread(o => { Thread.Sleep(3000); whenDone(42); }).Start();
        }

        static public int Do()
        {
            var mre = new ManualResetEvent(false);

            int retval = 0;
            DoAsync(i => { retval = i; mre.Set(); });

            if (mre.WaitOne())
                return retval;
            throw new ApplicationException("Unexpected error");
        }

        static void Main(string[] args)
        {
            Console.WriteLine(Do());
        }
    }
}