【发布时间】:2012-12-27 14:13:53
【问题描述】:
考虑这段代码:
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 文章"Calling Synchronous Methods Asynchronously" 发现了这个:
拨打BeginInvoke后,您可以执行以下操作:
- 做一些工作,然后调用
EndInvoke阻止直到调用 完成。 - 使用
IAsyncResultAsyncWaitHandle获取WaitHandle
属性,使用其WaitOne方法阻止执行,直到WaitHandle发出信号,然后调用EndInvoke。 - 轮询
BeginInvoke返回的IAsyncResult以确定何时 异步调用完成,然后调用EndInvoke。 - 将回调方法的委托传递给
BeginInvoke。方法 异步调用时在ThreadPool线程上执行 完成。回调方法调用EndInvoke。
我认为这一秒对我来说更好。但是如何实现呢?特别是我对重载WaitOne() (Blocks the current thread until the current WaitHandle receives a signal) 很感兴趣。如何正确地做到这一点?我的意思是这种情况下的常见模式。
更新:
现在我用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();
}
}
【问题讨论】:
标签: c# asynchronous begininvoke waithandle waitone