Async/AwaitとThreadingの両方を調べた後、それを自分の状況に適用する正しい方法がまだわかりません。目的の関数を非同期に呼び出していないように見えるため、UIを試しても、ハングしたままになります。さらに、実際にはソリューションにスレッドが必要な場合があります。
私がやろうとしていること: WPFアプリケーションがあり、UIを介してプログラムとの対話を許可する操作を開始したいボタンがあります。この関数の外部で決定された条件が満たされると、関数は終了するはずです。私にはこれはかなり標準に聞こえますが、私は何かを誤解していると感じており、間違って実装しています。
私が今持っているもの:
private async void start_button_Click(object sender, RoutedEventArgs e)
{
await StaticClass.MyFunction();
}
private void stop_button_Click(object sender, RoutedEventArgs e)
{
StaticClass.stopFlag = true;
}
public static Task<int> myFunction()
{
//Stuff Happens
while(StaticClass.stopFlag == false)
//Do Stuff
//Stuff Happens
return Task.FromResult(1) //I know this is bad, part of the reason I'm asking
}
私はこれに正しい方法でアプローチしているかどうかについてのガイダンスと、私が間違っていることに関する洞察を望んでいました。
あなたは間違いなくそれを間違って実装しました。 Task<int>
を返していますが、すべての作業が既に完了している場合のみを返します。
おそらく、同期メソッドが必要だと思われます。
private static void MyFunction()
{
// Loop in here
}
次に、次のようにタスクを開始します。
Task task = Task.Run((Action) MyFunction);
その後、必要に応じてそのタスクを待つことができます。指定した例では、await
の後に何もしないので、そうすることに意味はありません。
また、CancellationToken
を使用することは、他の場所の静的フラグよりもクリーンになることにもReedに同意します。
あなたは誤解しました。
_public static Task<int> myFunction()
{
//Stuff Happens
while(StaticClass.stopFlag == false)
//Do Stuff
//Stuff Happens
return Task.FromResult(1) //I know this is bad, part of the reason I'm asking
}
_
そのコードはすべて、最初のawait StaticClass.MyFunction();
呼び出しで発生します。呼び出し元に制御を返すことはありません。必要なのは、ループ部分を別のスレッドに入れることです。
_public static async Task myFunction()
{
//Stuff Happens on the original UI thread
await Task.Run(() => //This code runs on a new thread, control is returned to the caller on the UI thread.
{
while(StaticClass.stopFlag == false)
//Do Stuff
});
//Stuff Happens on the original UI thread after the loop exits.
}
_
このためにbool
を使用する代わりに、フレームワークに組み込まれている 管理されたキャンセルフレームワーク の使用を検討する必要があります。
基本的に、CancellationTokenSource
を構築し、キャンセルを処理するために使用できるメソッドにCancellationToken
を渡します。
最後に、現在のメソッドはUIスレッドを決して取得しません。 UIをブロックしない場合は、Task.Run
などを使用してメソッドをThreadPoolに移動する必要があります。
別の方法として、 BackgroundWorker クラスを使用してジョブを実行することもできます。UIは対話型のままです。