テキストボックスのテキストが既存のファイルを表す場合、カスタムイベントを呼び出すTextChanged
イベントのTextBox
があります。このイベントでは、ファイルに対して何らかの処理を行う外部dllへの呼び出しがあります。これは完了までに1分以上かかります。このメソッドが私に返す結果に依存して、私が行ういくつかの後処理もあります。現在、これはUIをブロックしていますが、これは非常に望ましくありません。UIをブロックせずに続行する前に結果を待つ
基本的に2つの「オプション」/シナリオがあります。
- カスタムイベント内では、何らかの形で、UIをフリーにしたままでイベントを続行する前に、dll呼び出しが完了するのを待ちます。これは私のマルチスレッド化されていない自己からの最も簡単なアイデアのようですが、概念的には私には赤い旗が投げられます:カスタムイベント自体(
TextChanged
から呼び出されます)がUIスレッドにあることを考えれば可能ですか? Task.Run()
を使用してカスタムイベント全体を独自のスレッドにスローします。ここでの欠点は、dllメソッドの呼び出しとは別に、longメソッドの後にgetter/setterの影響を受けるUI要素がかなりあることです。私は適切なInvokeRequired
に基づいて交互ゲッター/セッターを書くことができましたが、これを行うより正しい方法があれば、私はむしろそのアプローチを取っていきたいと思います。public partial class Form1 : Form { public Form1() { InitializeComponent(); comboBox1.Items.Add("Select One..."); comboBox1.Items.Add("Item 1"); comboBox1.Items.Add("Item 2"); Value = 0; } public string SetMessage { set { if (lblInfo.InvokeRequired) lblInfo.BeginInvoke((MethodInvoker)delegate() { lblInfo.Text = Important ? value + "!" : value; }); else lblInfo.Text = Important ? value + "!" : value; } } public bool Important { get { return chkImportant.Checked; } set { if (chkImportant.InvokeRequired) chkImportant.BeginInvoke((MethodInvoker) delegate() { chkImportant.Checked = value; }); else chkImportant.Checked = value; } } public SomeValue Value { get { if (comboBox1.InvokeRequired) { SomeValue v = (SomeValue)comboBox1.Invoke(new Func<SomeValue>(() => SomeValue.Bar)); return v; } else { switch (comboBox1.SelectedIndex) { case 1: return SomeValue.Foo; case 2: return SomeValue.Bar; default: return SomeValue.Nothing; } } } set { if (comboBox1.InvokeRequired) { comboBox1.BeginInvoke((MethodInvoker)delegate() { switch (value) { case SomeValue.Nothing: comboBox1.SelectedIndex = 0; break; case SomeValue.Foo: comboBox1.SelectedIndex = 1; break; case SomeValue.Bar: comboBox1.SelectedIndex = 2; break; } }); } else { switch (value) { case SomeValue.Nothing: comboBox1.SelectedIndex = 0; break; case SomeValue.Foo: comboBox1.SelectedIndex = 1; break; case SomeValue.Bar: comboBox1.SelectedIndex = 2; break; } } } } private void CustomEvent(object sender, EventArgs e) { if (!Important) Important = true; SetMessage = "Doing some stuff"; if (Value == SomeValue.Foo) Debug.WriteLine("Foo selected"); //I don't want to continue until a result is returned, //but I don't want to block UI either. if (ReturnsTrueEventually()) { Debug.WriteLine("True!"); } Important = false; SetMessage = "Finished."; } public bool ReturnsTrueEventually() { //Simulates some long running method call in a dll. //In reality, I would interpret an integer and return //an appropriate T/F value based on it. Thread.Sleep(5000); return true; } private void textBox1_TextChanged(object sender, EventArgs e) { //Do I *need* to multithread the whole thing? Task.Run(() => CustomEvent(this, new EventArgs())); } } public enum SomeValue { Nothing = 0, Foo = 100, Bar = 200 }
注を::
は、私が上からオプション2を使用して、私が後だものを基本的に示してはるかに短い(不自然ではあるが)サンプルプロジェクトを、作られた、私が求めていませんよ私のオプション2コードのコードレビュー。むしろ、オプション2を実行する必要があるかどうかを尋ねています。そのオプションは、プロセス全体を保持するメソッドが1つしかないので、コードのかなりの部分を変更するためです。
また、レプリケーションを防ぐためにこれらのプロパティのコードの一部を簡略化することもできます。自分自身にデモンストレーションし、デバッグするために、私はこの時点でそれを延期しています。ここで
が、私はオプション1(その呼び出すことなく、重複したコードとゲッター/セッターを左)に関連していたものです:
private async void CustomEvent(object sender, EventArgs e)
{
if (!Important)
Important = true;
SetMessage = "Doing some stuff";
if (Value == SomeValue.Foo)
Debug.WriteLine("Foo selected");
//I don't want to continue until a result is returned,
//but I don't want to block UI either.
if (await ReturnsTrueEventually())
{
Debug.WriteLine("True!");
}
Important = false;
SetMessage = "Finished.";
}
public async Task<bool> ReturnsTrueEventually()
{
//Simulates some long running method call in a dll.
//In reality, I would interpret an integer and
//return an appropriate T/F value based on it.
Thread.Sleep(5000);
return true;
}
2つのオプションを比較する場合は、オプション1を書き留めて、その違いを確認してください。 – Servy
async/awaitとtasksを使用してUIを応答可能にします。 .NET Frameworkのどのバージョンを使用していますか? – Dido
@Servy - 私がそれをしたとき、私は基本的に、私が終わりに戻るのを待っていることを思い出しました。私は正しく理解すれば、とにかくブロックしてしまいます。もちろん、私は完全に間違ったアプローチを取っている可能性があることを実現します... –