考虑这段代码:
class Program
{
static void Main(string[] args)
{
Master master = new Master();
master.Execute();
}
}
class TestClass
{
public void Method(string s)
{
Console.WriteLine(s);
Thread.Sleep(5000);
Console.WriteLine("End Method()");
}
}
class Master
{
private readonly TestClass test = new TestClass();
public void Execute()
{
Console.WriteLine("Start main thread..");
Action<String> act = test.Method;
IAsyncResult res = act.BeginInvoke("Start Method()..", x =>
{
Console.WriteLine("Start Callback..");
act.EndInvoke(x);
Console.WriteLine("End Callback");
}, null);
Console.WriteLine("End main thread");
Console.ReadLine();
}
}
我们有结果:
Start main thread..
End main thread
Start Method()..
End Method()
Start Callback..
End Callback
所以,我想要结果:
Start main thread..
Start Method()..
End Method()
Start Callback..
End Callback
End main thread
我怎么能async
在这段代码中等待?我查看了 MSDN 文章“异步调用同步方法”,发现:
调用后,BeginInvoke
您可以执行以下操作:
- 做一些工作,然后调用
EndInvoke
阻塞直到调用完成。 WaitHandle
使用该IAsyncResultAsyncWaitHandle
属性获取 a ,使用其WaitOne
方法阻止执行,直到
WaitHandle
发出信号,然后调用EndInvoke
.- 轮询
IAsyncResult
返回的 byBeginInvoke
以确定异步调用何时完成,然后调用EndInvoke
. - 将回调方法的委托传递给
BeginInvoke
. 当异步调用完成时,该方法在ThreadPool
线程上执行。回调方法调用EndInvoke
.
我认为这一秒对我来说更好。但是如何实现呢?特别是我对重载感兴趣WaitOne()
(阻塞当前线程,直到当前 WaitHandle 收到信号)。如何正确地做到这一点?我的意思是这种情况下的常见模式。
更新:
现在我使用Task<T>
:
class Program
{
static void Main(string[] args)
{
Master master = new Master();
master.Execute();
}
}
class WebService
{
public int GetResponse(int i)
{
Random rand = new Random();
i = i + rand.Next();
Console.WriteLine("Start GetResponse()");
Thread.Sleep(3000);
Console.WriteLine("End GetResponse()");
return i;
}
public void SomeMethod(List<int> list)
{
//Some work with list
Console.WriteLine("List.Count = {0}", list.Count);
}
}
class Master
{
private readonly WebService webService = new WebService();
public void Execute()
{
Console.WriteLine("Start main thread..");
List<int> listResponse = new List<int>();
for (int i = 0; i < 5; i++)
{
var task = Task<int>.Factory.StartNew(() => webService.GetResponse(1))
.ContinueWith(x =>
{
Console.WriteLine("Start Callback..");
listResponse.Add(x.Result);
Console.WriteLine("End Callback");
});
}
webService.SomeMethod(listResponse);
Console.WriteLine("End main thread..");
Console.ReadLine();
}
}
SomeMethod()
这是空的主要问题list
。
结果:
现在我有可怕的解决方案:(
public void Execute()
{
Console.WriteLine("Start main thread..");
List<int> listResponse = new List<int>();
int count = 0;
for (int i = 0; i < 5; i++)
{
var task = Task<int>.Factory.StartNew(() => webService.GetResponse(1))
.ContinueWith(x =>
{
Console.WriteLine("Start Callback..");
listResponse.Add(x.Result);
Console.WriteLine("End Callback");
count++;
if (count == 5)
{
webService.SomeMethod(listResponse);
}
});
}
Console.WriteLine("End main thread..");
Console.ReadLine();
}
结果:
这就是我需要等待异步调用的原因。我如何Wait
在Task
这里使用?
更新 2:
class Master
{
private readonly WebService webService = new WebService();
public delegate int GetResponseDelegate(int i);
public void Execute()
{
Console.WriteLine("Start main thread..");
GetResponseDelegate act = webService.GetResponse;
List<int> listRequests = new List<int>();
for (int i = 0; i < 5; i++)
{
act.BeginInvoke(1, (result =>
{
int req = act.EndInvoke(result);
listRequests.Add(req);
}), null);
}
webService.SomeMethod(listRequests);
Console.WriteLine("End main thread..");
Console.ReadLine();
}
}