次のコードを検討してください。
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
てから、呼び出しが完了するまでブロックを呼び出します。 -
プロパティを使用して を取得し、その
WaitHandle
メソッドを使用して が通知されるまで実行をブロックしてから、を呼び出します。IAsyncResultAsyncWaitHandle
WaitOne
WaitHandle
EndInvoke
IAsyncResult
によって返されたをポーリングしてBeginInvoke
、非同期呼び出しがいつ完了したかを判断してから、 を呼び出します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();
}
}