2010-08-30 17 views
3

为什么这不起作用?有什么办法可以在非WPF线程上使用Dispatcher;新的多线程

我在做什么: 我需要一种方法来运行特定线程中的特定方法,直到程序结束。

我的其他可能的选择: 据我了解可能的方法是执行一个队列。我可以推入我想要在特定线程中运行的方法。在特定的线程中,我将旋转并休眠/ monitor.pulse,以查看是否有委托等待在队列中运行。

我的目标: 是为了避免所有的努力去创建委托队列,保持锁等等。看起来,现成的解决方案存在于称为分派器的WPF世界中。 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. 
    } 
} 

回答

3

你不叫Dispatcher.Run。您假定Dispatcher包含Thread,它的工作,但这是倒退。第一次调用Dispatcher.CurrentDispatcher时,Dispatcher创建绑定到当前线程。请注意,即使您的代码不直接调用CurrentDispatcher,也会通过构建DispatcherObject(将CurrentDispatcher捕获到字段中)间接完成。

查看WPF threading model docs,其中包含您所需的所有详细信息。

如果你想在一个子线程调度器一样的功能,但不希望承担WPF的依赖,你可以使用从Nito.AsyncActionThread类,大致相当于一个Dispatcher还有一个专用Thread

相关问题