为什么这不起作用?
我的目标: 我需要一种方法来运行特定线程中的特定方法,直到程序结束。
我的其他可能选择: 我了解到一种可能的方法是实现一个队列。我可以将想要在特定线程中运行的方法推入该队列中。在特定线程中,我会旋转并睡眠/ monitor.pulse,以查看是否有委托等待在队列中运行。
我的目标: 是避免创建委托队列、维护锁等所有繁重的工作。似乎在WPF世界中存在一种现成的解决方案,称为Dispatcher。大多数WPF控件都从DispatcherObject继承,整个过程似乎都很好。我该怎么做才能让它起作用?
我的目标: 我需要一种方法来运行特定线程中的特定方法,直到程序结束。
我的其他可能选择: 我了解到一种可能的方法是实现一个队列。我可以将想要在特定线程中运行的方法推入该队列中。在特定线程中,我会旋转并睡眠/ monitor.pulse,以查看是否有委托等待在队列中运行。
我的目标: 是避免创建委托队列、维护锁等所有繁重的工作。似乎在WPF世界中存在一种现成的解决方案,称为Dispatcher。大多数WPF控件都从DispatcherObject继承,整个过程似乎都很好。我该怎么做才能让它起作用?
using System;
using System.Threading;
using System.Windows.Threading;
namespace ThreadingTrials
{
class Program
{
[STAThread]
static void Main(string[] args)
{
Thread.CurrentThread.Name = "mainThread";
Engine engine = new Engine();
Console.WriteLine("initializing SpecialEngine from {0}", Thread.CurrentThread.Name);
engine.initialize();
engine.doWork();
}
}
class Engine:DispatcherObject
{
private EventWaitHandle InitializationComplete;
private EventWaitHandle newWorkComplete;
//private Dispatcher dispatcher;
public Engine()
{
}
public void initialize()
{
InitializationComplete = new EventWaitHandle(false, EventResetMode.ManualReset);
Thread thread = new Thread(new ParameterizedThreadStart((hwnd)=>
{
InitializeSpecialEngineObject();
while (true) ;
}));
thread.Name = "Special Engine Thread";
thread.SetApartmentState(ApartmentState.STA);
thread.Priority = ThreadPriority.Normal;
thread.Start();
Console.WriteLine("waiting for initialize at {0}", Thread.CurrentThread.Name);
InitializationComplete.WaitOne();
}
private void InitializeSpecialEngineObject()
{
Console.WriteLine("doing initialization at {0}", Thread.CurrentThread.Name);
Thread.Sleep(500);
//dispatcher = Dispatcher.CurrentDispatcher;
InitializationComplete.Set();
}
internal void doWork()
{
newWorkComplete = new EventWaitHandle(false, EventResetMode.AutoReset);
//Dispatcher.Thread.Suspend();
Dispatcher.Invoke((SendOrPostCallback)delegate
{
Console.WriteLine("dispatched to {0}", Thread.CurrentThread.Name);
Thread.Sleep(500);
newWorkComplete.Set();
},DispatcherPriority.Background, null);
Dispatcher.Thread.Resume();
Console.WriteLine("waiting for new work to complete at {0}", Thread.CurrentThread.Name);
newWorkComplete.WaitOne();
}
private void doingWork()
{
Console.WriteLine("Doing work in {0}", Thread.CurrentThread.Name);
Thread.Sleep(500);
}
}
}
感谢您的输入。 说得好。实际上,制作一个简单的工作线程等待一个事件来表示队列中有新任务的void()委托,并在它们变得可用时运行它们,这是非常少的工作。我从在线网站复制了大部分代码...抱歉,我丢失了参考资料。我在那天做了这件事,应该更早地编辑这篇文章。
using System;
using System.Threading;
using System.Collections.Generic;
class ProducerConsumerQueue : IDisposable
{
EventWaitHandle _wh = new AutoResetEvent(false);
Thread _worker;
readonly object _locker = new object();
Queue<Action> _tasks = new Queue<Action>();
public delegate void Action();
public ProducerConsumerQueue()
{
_worker = new Thread(Work);
_worker.Start();
}
public void EnqueueTask(Action work)
{
lock (_locker) _tasks.Enqueue(work);
_wh.Set();
}
public void Dispose()
{
EnqueueTask(null); // Signal the consumer to exit.
_worker.Join(); // Wait for the consumer's thread to finish.
_wh.Close(); // Release any OS resources.
}
void Work()
{
while (true)
{
Action task = null;
lock (_locker)
if (_tasks.Count > 0)
{
task = _tasks.Dequeue();
if (task == null) return;
}
if (task != null)
{
task.Invoke();
}
else
_wh.WaitOne(); // No more tasks - wait for a signal
}
}
}
class Program
{
static void Main()
{
using (ProducerConsumerQueue q = new ProducerConsumerQueue())
{
q.EnqueueTask(delegate
{
Console.WriteLine("Performing task: Hello");
Thread.Sleep(1000); // simulate work...
});
for (int i = 0; i < 10; i++) q.EnqueueTask(delegate
{
Console.WriteLine("Performing task: "+ i);
Thread.Sleep(1000); // simulate work...
});
q.EnqueueTask(delegate
{
Console.WriteLine("Performing task: Goodbye!");
Thread.Sleep(1000); // simulate work...
});
}
// Exiting the using statement calls q's Dispose method, which
// enqueues a null task and waits until the consumer finishes.
}
}
Dispatcher.CurrentDispatcher
是一个带有副作用的属性(已经够糟糕了!),但我们还有Dispatcher.FromThread(…)
,这是一个执行完全相同操作的方法……只不过现在没有副作用了。小心! - Glenn Slayden