【问题标题】:Waiting for a 3rd party thread to finish等待第 3 方线程完成
【发布时间】:2013-02-16 19:56:04
【问题描述】:

我需要调用第 3 方代码,该代码可选地启动一个新线程,执行一些处理,然后在我的对象上调用不同的方法。我需要的是等待第 3 方处理完成,然后从原始方法返回。换句话说,我有一个这样的类(C#):

class MyClass: IThirdPartyInterface {
    void MyMethod() {
        //some preprocessing
        //call a 3rd party static method
        ThirdParty.DoSomething(this);
     }
    void FinishedProcessing() {
        //some postprocessing
        //???
    }
}

我想修改 MyMethod 使其仅在 DoSomething 中启动的线程完成执行并调用 FinishedProcessing 方法后才返回。由于线程是由第三方代码启动的,所以我无权访问,所以这里不能使用 Thread.Join。那么,我该怎么做呢?

【问题讨论】:

    标签: c# multithreading asynchronous


    【解决方案1】:

    你需要使用 System.Threading.AutoResetEvent,它应该是这样的:

    class MyClass: IThirdPartyInterface {
        AutoResetEvent _event = new AutoResetEvent(false);
        void MyMethod() {
            ThirdParty.DoSomething(this);
            _event.WaitOne();
        }
        void FinishedProcessing() {
            _event.Set();
        }
    }
    

    如果在你的 FinishedProcessing 方法被 3rdparty 类调用后线程继续运行,那就有点不同了:

    class MyClass: IThirdPartyInterface {
        AutoResetEvent _event = new AutoResetEvent(false);
        Thread _thread;
        void MyMethod() {
            ThirdParty.DoSomething(this);
            _event.WaitOne();
            _thread.Join();
        }
        void FinishedProcessing() {
            _thread = Thread.CurrentThread;
            _event.Set();
        }
    }
    

    【讨论】:

    • 谢谢!这里唯一缺少的是您必须将 _event 变量初始化为 new AutoResetEvent(false)
    【解决方案2】:

    使您的 MyMethod() 异步,然后在您的自定义 await 方法中运行第三方方法,如下所示:

    private async void MyMethod()
    {
        var result = await WaitAsynchronouslyAsync();
    }
    
    public async Task<string> WaitAsynchronouslyAsync()
    {
        await ThirdParty.DoSomething(this);
        return "Finished";
    }
    

    【讨论】:

    • 行不通,因为他解释说 DoSomething 调用一个新线程并返回。他想等待线程完成。
    • 另外,忘了说,如果可能的话,我是为了保持 3.5 的兼容性。
    【解决方案3】:

    如果 ThirdParty.DoSomething 不支持异步模式 您可以使用带有终结器的附加代理。 但它可能会像“while(myBoolFlag){}”一样影响应用程序性能。

    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<ManualResetEvent>();
            for (var i = 0; i < 10000; i++)
            {
                var m = new ManualResetEvent(false);
                list.Add(m);
                new Thread(Start).Start(m);
    
                if (i > 0 && (i % 10) == 0)
                    for (int j = i - 10; j < i; j++)
                    {
                        list[j].WaitOne(1000);// wait signal
                        GC.Collect(); //force finalizer
                        A.Print();
                }
            }
        }
    
        private static void Start(object obj)
        {
            new A(obj as ManualResetEvent, null);
        }
    }
    
    public class A : IThirdPartyInterface
    {
        public static long time1;
        public static long count1;
    
        private DateTime start = DateTime.Now;
        private ManualResetEvent _stop;
        private IThirdPartyInterface _origin;
        public A(ManualResetEvent stop, IThirdPartyInterface origin)
        {
            _stop = stop;
            _origin = origin;
        }
    
        ~A()
        {
            Interlocked.Increment(ref count1);
            Interlocked.Add(ref time1, (long)(DateTime.Now - start).TotalMilliseconds);
            _stop.Set(); //send signal
        }
    
        public static void Print()
        {
            Console.Write("\r" + A.time1 + "\\" + A.count1 + "    ");
            if (A.count1 != 0)
                Console.Write((A.time1 / A.count1).ToString());
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-02-15
      • 1970-01-01
      • 2015-08-29
      • 2011-06-09
      • 2010-10-16
      • 1970-01-01
      相关资源
      最近更新 更多