2010-04-07 33 views
1

我需要在我的课程中执行“Invoke()”方法,其行为与Control.Invoke()一样。如何在自定义类型中实现Control.Invoke模拟?

所以,当我从从创建实例线程不同的线程我InvokableEntity类的实例的工作,我将能够调用invokableEntity.Invoke(代表委托会在InvokableEntity的线程实例的上下文中执行是在创建。

是的,我读过this问题,它不会帮助我=(

请看看他的代码,它说明我尝试实施事件处理程序描述的行为(CustomProcessor_ProgressChanged方法应该从线程它被订阅的情况下被执行,但我不能这样做):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.ComponentModel; 
using System.Windows.Forms; 

namespace MultiThread 
{ 
    class Program 
    { 
     private static CustomProcessor customProcessor = new CustomProcessor(); 

     static void Main(string[] args) 
     { 
      Console.WriteLine("Worker was run from thread: {0}", Thread.CurrentThread.ManagedThreadId); 
      customProcessor.ProgressChanged += new EventHandler(CustomProcessor_ProgressChanged); 

      Thread workerThread = new Thread(customProcessor.Process); 
      AsyncOperation asyncOperation = AsyncOperationManager.CreateOperation(null); 
      //SynchronizationContext context = SynchronizationContext.Current; 
      workerThread.Start(asyncOperation); 

      Console.ReadLine(); 
     } 

     static void CustomProcessor_ProgressChanged(object sender, EventArgs e) 
     { 
      Console.WriteLine("Custom ProgressChanged was handled in thread: {0}", Thread.CurrentThread.ManagedThreadId); 
     } 
    } 

    class CustomProcessor 
    { 
     public event EventHandler ProgressChanged; 

     public void RaiseProcessChanged(object o) 
     { 
      Console.WriteLine("RaiseProgressChanged was handled in thread: {0}", Thread.CurrentThread.ManagedThreadId); 
      if (this.ProgressChanged != null) 
      { 
       this.ProgressChanged(this, EventArgs.Empty); 
      } 
     } 

     public void Process(object asyncOperation) 
     { 
      Console.WriteLine("CustomProcessor.Process method was executed in thread: {0}", Thread.CurrentThread.ManagedThreadId); 

      AsyncOperation asyncOperationInternal = (AsyncOperation)asyncOperation; 
      asyncOperationInternal.Post(this.RaiseProcessChanged, null); 

      //SynchronizationContext context = (SynchronizationContext) asyncOperation; 
      //context.Send(s => this.RaiseProcessChanged(null), null); 

      //this.RaiseProcessChanged(new object()); 
     } 
    } 
} 

谢谢!

+0

为什么没有这个问题(+一些很好的答案)可以帮助你? – 2010-04-07 09:18:51

+0

它只是不适合我,我不能得到可行的解决方案。调用总是在不同的线程中执行=( – Restuta 2010-04-07 09:25:12

+0

显示一些代码 – 2010-04-07 09:27:51

回答

2

Control.Invoke()使用PostMessage() API调用来发布将由主GUI线程的消息泵使用的消息。

让我们假设你在Thread#1创建CustomProcessor实例,它是不是一个GUI线程和创建的CustomProcessor的实例后,Thread#1那张具有悠久处理操作。如果您需要Invoke操作上Thread#1,你不想放弃当前的操作,这是一个好主意,而不是排队将由Thread#1每次消耗Thread#1完成任务的工作项。
如果没有逻辑排入从其它线程和出队新的工作和内Thread#1处理它,它不会神奇的工作外的开箱。

如果您在没有消息泵的多个线程上需要此功能,并且自定义类型不是从Control派生的,则可能会实现消息队列或等效项。这样,创建线程将在消息/工作队列循环中消耗其大部分时间,等待新工作 - 就像调用Application.Run()时Windows窗体应用程序中的主GUI线程一样。这可能不是你想要的。

+0

非常感谢,你给了我一个辉煌的解释! – Restuta 2010-04-07 13:37:34

2

编组从一个线程到另一个电话是一个相当大的把戏。所需要的是一种机制,可以确保目标线程处于空闲状态,并且可以运行执行请求,而不会有任何令人讨厌的重入问题的危险。

的的SynchronizationContext类是这样的机制的基类。它的默认实现并不实际同步任何东西,它在线程池线程上运行委托目标。

Windows窗体提供了一个类,做你正在寻找的东西,这WindowsFormsSynchronizationContext类。它依赖Application类中的消息循环来提供同步。这个类的一个实例被自动安装,Application.Run()方法负责处理它。 WPF也有一个DispatcherSynchronizationContext。

问题是:你永远不会被调用Application.Run()和你不运行的消息循环。所需的管道缺失。没有那个消息循环,你就无法得到你想要的东西。

+0

谢谢你,你的解释也很有帮助,谢谢你的时间! – Restuta 2010-04-07 13:38:05

相关问题