考慮以下代碼:如何使用WaitHandle等待異步調用的完成?
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",發現這個:
- 做一些工作,然後調用
EndInvoke
阻塞,直到通話 完成:調用
BeginInvoke
你可以做以下後。 - 獲取一個
WaitHandle
使用IAsyncResultAsyncWaitHandle
屬性,使用其WaitOne
方法,直到
WaitHandle
用信號阻斷執行,然後調用EndInvoke
。 - 輪詢
IAsyncResult
返回BeginInvoke
確定何時 異步調用已完成,然後調用EndInvoke
。 - 將回調方法的代理傳遞給
BeginInvoke
。當異步調用 完成時,方法 在ThreadPool
線程上執行。回調方法調用EndInvoke
。
我覺得這個第二個更好的變種。但是怎麼實現呢?特別是我感興趣超載WaitOne()
(Blocks the current thread until the current WaitHandle receives a signal)。如何正確做到這一點?我的意思是這種情況下的常見模式。
UPDATE:
現在我用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();
}
}
感謝您的回覆!看來,這是我需要的! :) – Alexandr
哈姆雷特,你可以請檢查我的更新2後?我對學術目的感興趣,如果使用異步BeginInvoke()是否可以實現與您的答覆中相同的結果? – Alexandr