通用BeginInvoke方案,以确保在相同的线程上下文中调用函数 [英] Generic BeginInvoke Scheme to ensure function calls in same threading context

查看:146
本文介绍了通用BeginInvoke方案,以确保在相同的线程上下文中调用函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将一些代码从winforms控制对象移到一个单独的对象,以实现更好的模块化.但是,有一些对发出回调的外部对象的调用,我无法控制这些回调,并且可以从不同线程中将其作为主UI线程触发.为了避免这种情况,我使用众所周知的BeginInvoke方案来检查是否应将调用转移到主UI线程.

I'm moving some code from a winforms control object to a separate object for better modularity. However, there some calls to an external object issuing callbacks, which I have no control of and which can be fired from different threads as the main UI thread. To avoid this I use the well known BeginInvoke scheme to check, whether a call should be transfered to the main UI thread.

现在,当我将此代码移到我的分离对象时,就不再需要Winforms引用了.我可以处理Control对象,以确保所有内容都在同一线程中运行.但是我想拥有一个通用机制,其功能与确保Threadconext完全相同,例如创建对象或调用特定的入口函数也用于后续发出的调用,例如通过外部回调.

When I now move this code to my separated object, I have not necessary a Winforms reference anymore. I could handle over a Control object to still ensure that everything is running in the same thread. But I would rather like to have a generic mechanism which does exactly the same like ensuring, that the Threadconext in which the e.g. the object was created or a specific entry function was called is also used for subsequent calls issued e.g. by external callbacks.

这最容易实现吗?

示例:

public class Example
{
    ThreadedComponent _Cmp = new ThreadedComponent();


    public Example()
    {
        _Cmp.ThreadedCallback += new ThreadedComponent.CB(Callback);

    }

   public void StartFunction()
   {
        // called in ThreadContextA
        _Cmp.Start();

   }

   void Callback(Status s)
   {
     // is called in ThreadContextB
     if(s == SomeStatus)
       _Cmp.ContinueFunction(); // must be called in ThreadContextA

   } 
}

为澄清起见

ContinueFunction.这不一定是UI线程,但目前它当然是按钮处理程序.

ContinueFunction must be called from the same ThreadContext like StartFunction was called. This is not necessarily a UI thread, but at the moment it is of course a button handler.

推荐答案

我使用运行自己的线程的单独队列解决了该问题.通过代理接口将函数调用添加到队列中.这可能不是最优雅的方法,但可以确保添加到队列中的所有内容都在队列的线程上下文中执行.这是一个非常原始的实现示例,仅用于展示基本思想:

I solve the problem using a separate queue which runs its own thread. Function Calls are added to the Queue with a Proxyinterface. It's probably not the most elegant way, but it ensures, that everything added to the queue is executed in the queue's threadcontext. This is a very primitive implementation example just to show the basic idea:

public class Example
{
   ThreadQueue        _QA = new ThreadQueue();
   ThreadedComponent _Cmp = new ThreadedComponent();


   public Example()
   {
       _Cmp.ThreadedCallback += new ThreadedComponent.CB(Callback);
    _QA.Start();
    }

    public void StartFunction()
    {
        _QA.Enqueue(AT.Start, _Cmp);
    }

    void Callback(Status s)
    {
    // is called in ThreadContextB
    if(s == SomeStatus)
       _QA.Enqueue(new ThreadCompAction(AT.Continue, _Cmp);
    } 
}

public class ThreadQueue
{
   public Queue<IThreadAction> _qActions = new Queue<IThreadAction>();

   public Enqueue(IThreadAction a)
   {
         lock(_qActions)
             _qActions.Enqueue(a);
   }

   public void Start()
   {
      _thWatchLoop        = new Thread(new ThreadStart(ThreadWatchLoop));
      _thWatchLoop.Start();
   }

   void ThreadWatchLoop()
   {   
        // ThreadContext C
        while(!bExitLoop)
        {
            lock (_qActions)
            {
                while(_qActions.Count > 0)
                {

                    IThreadAction a = _qActions.Dequeue();
                    a.Execute();
                }
            }
        }
   }
}

public class ThreadCmpAction : IThreadAction
{
     ThreadedComponent  _Inst;
     ActionType         _AT;
     ThreadCmpAction(ActionType AT, ThreadedComponent _Inst) 
     {
        _Inst = Inst;
        _AT   = AT;
     }

     void Do()
     {
        switch(AT)
        {
           case AT.Start:
              _Inst.Start();
           case AT.Continue:
             _Inst.ContinueFunction;
        }
     }
}

这篇关于通用BeginInvoke方案,以确保在相同的线程上下文中调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆