【发布时间】:2016-09-16 09:18:57
【问题描述】:
我需要调用一个满足以下条件的方法。
- 该方法可能会运行数小时。
- 该方法可以与硬件接口。
- 该方法可能会请求用户输入(参数值、确认等)。该请求应阻止该方法,直到收到输入为止。
我有一个使用以下设计满足此标准的原型实现。
假设存在Form 并包含Panel。
IntegerInput 类是一个 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 并调用RunTestAsync 传递Form1UserInput 的实例。
我知道一些关于长时间运行的任务可能会阻塞以及这对ThreadPool 资源意味着什么的担忧。但是,我正在构建的应用程序不提供一次调用多个方法的能力。当调用的方法正在运行时,应用程序可能会提供一些其他有限的功能,但当前的要求并未详细指定此类功能。我预计任何时候都只会有一个长时间运行的线程在服务中。
对这种类型的方法调用使用 Task.Run() 是合理的实现吗?如果不是,那么提供所需标准的更合理的实施是什么?我是否应该为此调用考虑在 ThreadPool 之外使用专用线程?
【问题讨论】:
-
停止
async void唯一可以使用的情况是当您有事件处理程序并且您无法更改返回类型时。
标签: c# multithreading async-await task-parallel-library .net-4.5