zoukankan      html  css  js  c++  java
  • 实现ISynchronizeInvoke

    实现ISynchronizeInvoke

            当运行于线程T1的客户端调用一个对象的方法的时候,该对象的方法是在客户端线程上执行的。然而,如果该对象的方法要求始终在一个指定线程T2上执行,该怎么实现呢?这是要求多个线程配合使用的常见情形。例如,.NET Windows窗体和控件要求必须在创建它们的那个线程里处理消息。为了处理这样的情况,.NET提供了ISynchronizeInvoke接口。本文演示了如何实现ISynchronizeInvoke接口,Synchronizer类。Synchronizer类是ISynchronizeInvoke接口的一个通用实现。你可以继承它来进行扩充,也可以直接使用它作为你实现ISynchronizeInvoke的类的成员,代理ISynchronizeInvoke的行为。

    public delegate int AddDelegate(int arg1, int arg2);

    public class Calculator
    {
        
    public int Add(int arg1, int arg2)
         
    {
             
    int threadId = Thread.CurrentThread.GetHashCode();
            Console.WriteLine(
    "Calculator thread ID is " + threadId.ToString());
            Thread.Sleep(
    5000);
            
    return arg1 + arg2;
        }

    }

    [Serializable]
    class WorkItem : IAsyncResult
    {
        
    object[] mArgs;
        
    object mAsyncState;
        
    bool mCompleted;
        Delegate mMethod;
        ManualResetEvent mEvent;
        
    object mMethodReturnedValue;
        
        
    public WorkItem(object asyncState, Delegate method, object[] args)
        
    {
            mAsyncState 
    = asyncState;
            mMethod 
    = method;
            mArgs 
    = args;
            mEvent 
    = new ManualResetEvent(false);
            mCompleted 
    = false;
        }

        
        
    //IAsyncResult properties 
        object IAsyncResult.AsyncState
        
    {
            
    get return mAsyncState; }
        }

        
        WaitHandle IAsyncResult.AsyncWaitHandle
        
    {
            
    get return mEvent; }
        }

        
        
    bool IAsyncResult.CompletedSynchronously
        
    {
            
    get return false; }
        }

        
        
    bool IAsyncResult.IsCompleted
        
    {
            
    get return mCompleted; }
        }

        
        
    bool Completed
        
    {
            
    get lock(thisreturn mCompleted; } }
            
    set lock(this{ mCompleted = value;} }
        }

        
        
    public void CallBack()
        
    {
            MethodReturnedValue 
    = mMethod.DynamicInvoke(mArgs);
            mEvent.Set();
            Completed 
    = true;
        }

        
        
    public object MethodReturnedValue
        
    {
            
    get 
            
    {
                
    object methodReturnedValue;
                
    lock (this)
                
    {
                    methodReturnedValue 
    = mMethodReturnedValue;
                }

                
    return methodReturnedValue;
            }

            
    set
            
    {
                
    lock (this)
                
    {
                    mMethodReturnedValue 
    = value;
                }

            }

        }
            
    }
    class WorkerThread
    {
        
    public Thread mThreadObj;
        
    bool mEndLoop;
        Mutex mEndLoopMutex;
        AutoResetEvent mItemAdded;
        Synchronizer mSynchronizer;
        Queue mWorkItemQueue;
        
        
    public WorkerThread(Synchronizer synchronizer)
        
    {
            mSynchronizer 
    = synchronizer;
            mEndLoop 
    = false;
            mThreadObj 
    = null;
            mEndLoopMutex 
    = new Mutex();
            mItemAdded 
    = new AutoResetEvent(false);
            mWorkItemQueue 
    = new Queue();
            CreateThread(
    true);
        }

        
        
    public void QueueWorkItem(WorkItem workItem)
        
    {
            
    lock (mWorkItemQueue.SyncRoot)
            
    {
                mWorkItemQueue.Enqueue(workItem);
                mItemAdded.Set();
            }

        }

        
        
    bool EndLoop
        
    {
            
    get
            
    {
                
    bool result = false;
                mEndLoopMutex.WaitOne();
                result 
    = mEndLoop;
                mEndLoopMutex.ReleaseMutex();
                
    return result;
            }

            
    set
            
    {
                mEndLoopMutex.WaitOne();
                mEndLoop 
    = value;
                mEndLoopMutex.ReleaseMutex();
            }

        }

        
        Thread CreateThread(
    bool autoStart)
        
    {
            
    if (mThreadObj != null)
            
    {
                Debug.Assert(
    false);
                
    return mThreadObj;
            }

            ThreadStart threadStart 
    = new ThreadStart(Run);
            mThreadObj 
    = new Thread(threadStart);
            mThreadObj.Name 
    = "Synchronizer Worker Thread";
            
    if (autoStart)
            
    {
                mThreadObj.Start();
            }

            
    return mThreadObj;
        }

        
        
    void Start()
        
    {
            Debug.Assert(mThreadObj 
    != null);
            Debug.Assert(mThreadObj.IsAlive 
    == false);
            mThreadObj.Start();
        }
        
        
        
    bool QueueEmpty
        
    {
            
    get
            
    {
                
    lock (mWorkItemQueue.SyncRoot)
                
    {
                    
    if (mWorkItemQueue.Count > 0)
                        
    return false;
                    
    return true;
                }

            }

        }

        
        WorkItem GetNext()
        
    {
            
    if (QueueEmpty) return null;
            
    lock (mWorkItemQueue.SyncRoot)
            
    {
                
    return (WorkItem)mWorkItemQueue.Dequeue();
            }

        }

        
        
    void Run()
        
    {
            
    while (EndLoop == false)
            
    {
                
    while (QueueEmpty == false)
                
    {
                    
    if (EndLoop)
                        
    return;
                    WorkItem workItem 
    = GetNext();
                    workItem.CallBack();
                }

                mItemAdded.WaitOne();
            }

        }

        
        
    public void Kill()
        
    {
            Debug.Assert(mThreadObj 
    != null);
            
    if (mThreadObj.IsAlive == false)
            
    {
                
    return;
            }

            EndLoop 
    = true;
            mItemAdded.Set();
            
            
    // wait for thead to die
            mThreadObj.Join();
            
    if (mEndLoopMutex != null)
                mEndLoopMutex.Close();
            
    if (mItemAdded != null)
                mItemAdded.Close();
        }

    }
    public class Synchronizer: ISynchronizeInvoke,IDisposable
    {
        WorkerThread mWorkerThread;
        
        
    public bool InvokeRequired
        
    {
            
    get
            
    {
                
    bool res = Object.ReferenceEquals(Thread.CurrentThread, mWorkerThread.mThreadObj);
                
    return res;
            }

        }

        
        
    public IAsyncResult BeginInvoke(Delegate method, Object[] args)
        
    {
            WorkItem result 
    = new WorkItem(null, method, args);
            mWorkerThread.QueueWorkItem(result);
            
    return result;
        }

        
        
    public object EndInvoke(IAsyncResult result)
        
    {
            result.AsyncWaitHandle.WaitOne();
            WorkItem workItem 
    = (WorkItem)result;
            
    return workItem.MethodReturnedValue;
        }

        
        
    public object Invoke(Delegate method, object[] args)
        
    {
            IAsyncResult asyncResult;
            asyncResult 
    = BeginInvoke(method,args);
            
    return EndInvoke(asyncResult);
        }

        
        
    public Synchronizer()
        
    {
            mWorkerThread 
    = new WorkerThread(this);
        }

        
        
    ~Synchronizer()
        
    {
        }

        
        
    public void Dispose()
        
    {
            mWorkerThread.Kill();
        }

    }
    public class Tester : IDisposable
    {
        Synchronizer mSynchronizer;
        
    public Tester()
        
    {
            
    int threadId = Thread.CurrentThread.GetHashCode();
            Console.WriteLine(
    "Main Thread Id is: " + threadId.ToString());
            mSynchronizer 
    = new Synchronizer();
        }

        
        
    public void TestSynchCall()
        
    {
            Calculator  calc   
    = new Calculator();
            AddDelegate addDelegate 
    = new AddDelegate(calc.Add);
            
    object[] arr = new object[2];
            arr[
    0= 15;
            arr[
    1= 38;
            
    object sum = 0;
            sum 
    = mSynchronizer.Invoke(addDelegate,arr);
            Console.WriteLine(
    "TestSynchCall: result is " + sum.ToString());
        }

        
        
    public void TestAsyncCall()
        
    {
            Calculator  calc   
    = new Calculator();
            AddDelegate addDelegate 
    = new AddDelegate(calc.Add);
            
    object[] arr = new object[2];
            arr[
    0= 33;
            arr[
    1= 19;
            IAsyncResult result  
    = mSynchronizer.BeginInvoke(addDelegate,arr);
            
            Console.WriteLine(
    "wait for get result from Async Call");
            
    object sum = mSynchronizer.EndInvoke(result);
            Console.WriteLine(
    "TestAsyncCall: result is " + sum.ToString());
        }

       
        
    public void Dispose()
        
    {
            mSynchronizer.Dispose();
        }

        
    }

        
    public class MyClass
    {
        
    public static void Main(string[] args)
        
    {
            
    using (Tester tester = new Tester())
            
    {
                
    //tester.TestSynchCall();
                tester.TestAsyncCall();
            }

            Console.ReadLine();
        }

    }
  • 相关阅读:
    【CI】系列一:总体环境规划
    【原】Ubuntu下使用teamviewer
    [Android] android:visibility属性应用
    Android 软键盘
    android EditText inputType 及 android:imeOptions=”actionDone”
    【Android】The application has stopped unexpectedly.Please try again.
    【IntelliJ IDEA 12使用】导入外部包
    [转载]Android开发者必须深入学习的10个应用开源项目
    【android相关】【问题解决】R.java文件丢失
    1月1日起,我市交通事故快速理赔上限提高至1万元!
  • 原文地址:https://www.cnblogs.com/hcfalan/p/504768.html
Copyright © 2011-2022 走看看