次の基準を満たすメソッドを呼び出す必要があります。ハードウェアインタフェースのスレッド呼び出しにTask.Run()を使用する
- このメソッドは数時間実行される可能性があります。
- このメソッドは、ハードウェアとインターフェースできます。
- このメソッドは、ユーザー入力(パラメーター値、確認など)を要求する場合があります。リクエストは、入力が受信されるまでメソッドをブロックする必要があります。
私は、次の設計を使用してこの基準を満たすプロトタイプの実装を行っています。
Form
が存在し、Panel
を含むものとします。
UserControl
は、TextBox
とButton
です。
public partial class IntegerInput : UserControl
{
public TaskCompletionSource<int> InputVal = new TaskCompletionSource<int>(0);
public IntegerInput()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int val = 0;
Int32.TryParse(textBox1.Text, out val);
InputVal.SetResult(val);
}
}
Form1UserInput
クラスはForm1
によってインスタンス化されます。 container
はForm1
で設定されたPanel
で、呼び出し元のクラスに提供されます。
public interface IUserInput
{
Task<int> GetInteger();
}
public class Form1UserInput : IUserInput
{
public Control container;
private IntegerInput integerInput = new IntegerInput();
public IntegerInput IntegerInput { get { return integerInput; } }
public async Task<int> GetInteger()
{
container.Invoke(new Action(() =>
{
container.Controls.Clear();
container.Controls.Add(integerInput);
}));
await integerInput.InputVal.Task;
return integerInput.InputVal.Task.Result;
}
}
Demo
クラスは、私が呼び出したいメソッドが含まれています。
public class Demo
{
public IUserInput ui;
public async void MethodToInvoke()
{
// Interface with hardware...
// Block waiting on input
int val = await ui.GetInteger();
// Interface with hardware some more...
}
public async void AnotherMethodToInvoke()
{
// Interface with hardware...
// Block waiting on multiple input
int val1 = await ui.getInteger();
int val2 = await ui.getInteger();
// Interface with hardware...
}
}
これは、呼び出し元のクラスの外観の概要です。 Task.Run()
の呼び出しは私のプロトタイプでは正確です。
public class Invoker
{
public async Task RunTestAsync(IUserInput ui)
{
object DemoInstance = Activator.CreateInstance(typeof(Demo));
MethodInfo method = typeof(Demo).GetMethod("MethodToInvoke");
object[] args = null;
((IUserInput)DemoInstance).ui = ui;
var t = await Task.Run(() => method.Invoke(DemoInstance, args));
// Report completion information back to Form1
}
}
Form1
コントローラクラスインスタンスInvoker
とForm1UserInput
のインスタンスでRunTestAsync
通過を呼び出します。
長時間実行されているブロックされているタスクや、ThreadPool
リソースの意味についてはいくつか懸念しています。しかし、一度に複数のメソッドを呼び出す機能は、私が構築しているアプリケーションでは提供されていません。呼び出されたメソッドが実行されている最中に、現在の要件でそのような機能を詳細に指定していない間に、アプリケーションがその他の限られた機能を提供する可能性があります。私は、いつでも1つの長時間稼動しているスレッドしか稼働していないことが予想されます。
このタイプのメソッド呼び出しにTask.Run()を使用するのは合理的な実装ですか?そうでない場合、必要な基準を提供するより合理的な実装は何でしょうか?私は、この呼び出しのためにThreadPoolの外に専用のスレッドを考慮する必要がありますか?
ストップを使用すると、イベントハンドラを持っている場合、使用することが許容される唯一の時間は '非同期void'を行うと、戻り値の型は変更できません。 –