タスクを委任し、完了時に通知を受け取る (C# の場合)
-
09-06-2019 - |
質問
概念的には、次のことを実現したいと考えていますが、C# で適切にコーディングする方法を理解するのに苦労しています。
SomeMethod { // Member of AClass{}
DoSomething;
Start WorkerMethod() from BClass in another thread;
DoSomethingElse;
}
次に、WorkerMethod() が完了したら、これを実行します。
void SomeOtherMethod() // Also member of AClass{}
{ ... }
誰かその例を挙げてもらえますか?
解決
の 背景労働者 クラスはまさにこの目的のために .NET 2.0 に追加されました。
簡単に言うと、次のことを行います。
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate { myBClass.DoHardWork(); }
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(SomeOtherMethod);
worker.RunWorkerAsync();
必要に応じて、キャンセルや進捗レポートなどの派手な機能を追加することもできます:)
他のヒント
.Net 2 では、BackgroundWorker が導入され、非同期操作の実行が非常に簡単になりました。
BackgroundWorker bw = new BackgroundWorker { WorkerReportsProgress = true };
bw.DoWork += (sender, e) =>
{
//what happens here must not touch the form
//as it's in a different thread
};
bw.ProgressChanged += ( sender, e ) =>
{
//update progress bars here
};
bw.RunWorkerCompleted += (sender, e) =>
{
//now you're back in the UI thread you can update the form
//remember to dispose of bw now
};
worker.RunWorkerAsync();
.Net 1 ではスレッドを使用する必要があります。
AsyncCallBacks を使用する必要があります。AsyncCallBacks を使用してメソッドへのデリゲートを指定し、ターゲット メソッドの実行が完了すると呼び出される CallBack メソッドを指定できます。
これは小さな例です。実行して自分の目で確認してください。
クラスプログラム{
public delegate void AsyncMethodCaller();
public static void WorkerMethod()
{
Console.WriteLine("I am the first method that is called.");
Thread.Sleep(5000);
Console.WriteLine("Exiting from WorkerMethod.");
}
public static void SomeOtherMethod(IAsyncResult result)
{
Console.WriteLine("I am called after the Worker Method completes.");
}
static void Main(string[] args)
{
AsyncMethodCaller asyncCaller = new AsyncMethodCaller(WorkerMethod);
AsyncCallback callBack = new AsyncCallback(SomeOtherMethod);
IAsyncResult result = asyncCaller.BeginInvoke(callBack, null);
Console.WriteLine("Worker method has been called.");
Console.WriteLine("Waiting for all invocations to complete.");
Console.Read();
}
}
ここにはいくつかの可能性がありますが、私は非同期的に呼び出されるデリゲートを使用します。 BeginInvoke
方法。
警告 :いつも電話するのを忘れないでください EndInvoke
で IAsyncResult
で説明されているように、最終的なメモリ リークを回避するため この記事.
BackgroundWorker を確認してください。
非同期デリゲートを使用します。
// Method that does the real work
public int SomeMethod(int someInput)
{
Thread.Sleep(20);
Console.WriteLine(”Processed input : {0}”,someInput);
return someInput+1;
}
// Method that will be called after work is complete
public void EndSomeOtherMethod(IAsyncResult result)
{
SomeMethodDelegate myDelegate = result.AsyncState as SomeMethodDelegate;
// obtain the result
int resultVal = myDelegate.EndInvoke(result);
Console.WriteLine(”Returned output : {0}”,resultVal);
}
// Define a delegate
delegate int SomeMethodDelegate(int someInput);
SomeMethodDelegate someMethodDelegate = SomeMethod;
// Call the method that does the real work
// Give the method name that must be called once the work is completed.
someMethodDelegate.BeginInvoke(10, // Input parameter to SomeMethod()
EndSomeOtherMethod, // Callback Method
someMethodDelegate); // AsyncState
わかりました。これをどのようにしたいのかわかりません。あなたの例から、WorkerMethod は実行する独自のスレッドを作成しないようですが、そのメソッドを別のスレッドで呼び出したいと考えています。
その場合は、WorkerMethod を呼び出してから SomeOtherMethod を呼び出す短いワーカー メソッドを作成し、そのメソッドを別のスレッドのキューに入れます。その後、WorkerMethod が完了すると、SomeOtherMethod が呼び出されます。例えば:
public class AClass
{
public void SomeMethod()
{
DoSomething();
ThreadPool.QueueUserWorkItem(delegate(object state)
{
BClass.WorkerMethod();
SomeOtherMethod();
});
DoSomethingElse();
}
private void SomeOtherMethod()
{
// handle the fact that WorkerMethod has completed.
// Note that this is called on the Worker Thread, not
// the main thread.
}
}