我目前正在自学 C#,我在编程方面有点陌生,所以如果这涉及到另一个主题(我尝试搜索),请提前致歉。
我一直在尝试创建一个通用的 worker/thread 类,它采用一种方法,该方法专门包含一长串过程步骤。这个想法是能够以类似于在 Visual Studio 中设置断点以暂停/取消暂停的方式暂停/恢复它。为了提供上下文,我主要使用 ASP.NET 和 XAML WPF 接口(interface)(目前为 XAML)进行自动化。
我的理解是我需要使用某种委托(delegate),但我正在寻找一个非常简单的简单示例。我发现的示例是一个完全不同的范围,我很难在其他上下文中遵循提供的解决方案。
从 MSDN 和 Stackoverflow 上的其他示例来看,“任务”工作类是我目前所拥有的,但我对 DoDelegatedMethod 和我的构造函数的位置有点不知所措。我在这里要做的是实例化一个 Task 对象,在新实例化时传入一个委托(delegate)方法,创建一个新线程,并将传入的方法与线程结合起来。
我想要通用“任务”的原因是这样我就可以通用地管理特定方法,而不必为每个实例编写不同的“DoWork”方法。
这是正确的方法吗?
class Task
{
private ManualResetEvent _shutdownFlag = new ManualResetEvent(false);
private ManualResetEvent _pauseFlag = new ManualResetEvent(true);
private delegate void MyDelegate();
Thread _thread;
public Task() { }
public Task(MyDelegate d = new MyDelegate(DoStuff)) // ERROR
{
_thread = new Thread(DoDelegatedMethod); // ERROR
}
public void Start()
{
_thread.Start();
}
public void Resume()
{
_pauseFlag.Set(); ;
}
public void Stop()
{
_shutdownFlag.Set();
_pauseFlag.Set();
_thread.Join();
}
private void DoDelegatedMethod(MyDelegate d)
{
do
{
d();
}
while (!_shutdownFlag.WaitOne(0));
}
// This does nothing but spin forever until I force it to stop
public void Spin()
{
do
{
// MessageBox.Show("test");
_pauseFlag.WaitOne(Timeout.Infinite);
}
while (!_shutdownFlag.WaitOne(0));
//MessageBox.Show("thread over");
}
}
最佳答案
new Thread()
采用 ThreadStart(或 ParameterisedThreadStart)参数,而您的 DoDelegatedMethod 回调没有正确的 ThreadStart 签名。所以你需要这样写:
ThreadStart method = new ThreadStart(() => DoDelegatedMethod(d));
_thread = new Thread(method);
这会创建一个匿名回调(() => DoDelegatedMethod(d)
位),它在运行时将使用委托(delegate) d
(已“捕获”)调用 DoDelegatedMethod通过匿名方法)。现在您将此匿名回调传递给 Thread 构造函数,因此当线程运行时,它将调用匿名回调,后者将依次调用 DoDelegatedMethod(d)。实际上,lambda 使 DoDelegatedMethod 适应 ThreadStart 签名。
另一种方法是将 DoDelegatedMethod 更改为不带参数,并将 d
存储为 DoDelegateMethod 将访问的 Task 类的成员字段。
此外,构造函数出错的原因是默认值只能是一组有限的类型,而委托(delegate)不是其中之一(只有属性中允许的类型,如 int、long、字符串和类型是允许的)。改用重载:
public Task() : this(new MyDelegate(DoStuff)) { ... }
public Task(MyDelegate d) { ... }
请注意,如果 DoStuff 是 Task 的实例方法,您仍然可能会收到错误消息——这并不清楚。我个人认为让 Task
运行的默认委托(delegate)设计有点奇怪,因此您可能只想摆脱默认构造函数。
根据评论中的讨论,我认为有必要总结一下对 Task 类的建议修改:
public class Task
{
private readonly Action _action;
// other members as before
// default constructor removed
public Task(Action action)
{
_action = action;
}
public void Start()
{
ThreadStart ts = new ThreadStart(DoDelegatedMethod);
_thread = new Thread(ts);
_thread.Start();
}
private void DoDelegatedMethod()
{
do
{
_action();
}
while (!_shutdownFlag.WaitOne(0));
}
// other members as before
}
以及用法:
Task task = new Task(this.AutomatedTasks);
task.Start();
private void AutomatedTasks() { ... }
关于c# - 如何使用委托(delegate)在线程包装器类中传递方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4973892/