简体   繁体   English

使用线程从两个长期运行的方法返回值

[英]Return values from two long running methods, using threads

I have a thread that connects to two network resources. 我有一个连接到两个网络资源的线程。 Each time I attempt a connection, it can take 10 seconds for a reply. 每次尝试建立连接时,回复可能需要10秒钟。

void MyThread()
{
    //this takes ten seconds
    Resource r1 = MySystem.GetResource(ipAddress1);

    //this takes ten seconds
    Resource r2 = MySystem.GetResource(ipAddress2);

    //do stuff with ep1 and ep2
} 

Total time is twenty seconds, but I'd really like it to take only ten seconds -- launching threads each time I call GetResource, receiving a reply and then joining each thread to return control. 总时间为20秒,但是我真的希望它仅花费10秒-每次我调用GetResource时启动线程,接收答复,然后加入每个线程以返回控制权。

What's the best way to do this? 最好的方法是什么? Launch two threads that each return a value? 启动两个各自返回值的线程? Anonymous methods that take references to local variables? 引用局部变量的匿名方法? My head is spinning. 我的头在旋转。 Code is appreciated. 代码受到赞赏。

How about 怎么样

Resource r1 = null; // need to initialize, else compiler complains
Resource r2 = null;

ThreadStart ts1 = delegate {
    r1 = MySystem.GetResource(ipAddress1);
};
ThreadStart ts2 = delegate {
    r2 = MySystem.GetResource(ipAddress2);
};
Thread t1 = new Thread(ts1);
Thread t2 = new Thread(ts2);
t1.Start();
t2.Start();
// do some useful work here, while the threads do their thing...
t1.Join();
t2.Join();
// r1, r2 now setup

Short and sweet. 简短而甜美。

The easiest way that occurs to me to do so is to parallelize one of the calls on a worker thread while having the main thread perform the second initialization and wait. 对我而言,最简单的方法是并行化工作线程上的调用之一,同时让主线程执行第二次初始化并等待。 The following snipet should help to illustrate: 以下摘录应有助于说明:

ManualResetEvent r1Handle = new ManualResetEvent(false);
Resource         r1       = null;
Resource         r2       = null;

// Make the threadpool responsible for populating the 
// first resource.

ThreadPool.QueueUserWorkItem( (state) =>
{
  r1 = MySystem.GetResource(ipAddress1);

  // Set the wait handle to signal the main thread that
  // the work is complete.

  r1Handle.Set();
});

// Populate the second resource.

r2 = MySystem.GetResource(ipAddress2);

// Wait for the threadpool worker to finish.

r1Handle.WaitOne();

// ... Do more stuff

For a more detailed discussion of thread synchronization techniques, you may wish to visit the MSDN article on the topic: http://msdn.microsoft.com/en-us/library/ms173179.aspx 有关线程同步技术的详细讨论,您可能希望访问有关该主题的MSDN文章: http://msdn.microsoft.com/en-us/library/ms173179.aspx : http://msdn.microsoft.com/en-us/library/ms173179.aspx

These are always fun questions to ponder, and of course there's multiple ways to solve it. 这些总是值得思考的有趣问题,当然,有多种解决方法。

One approach that's worked well for me is to provide a callback method that each thread uses to pass back results and status. 对我而言,一种行之有效的方法是提供一种回调方法,每个线程都使用该方法来传回结果和状态。 In the following example, I use a List to keep track of running threads and put the results in a Dictionary. 在下面的示例中,我使用List来跟踪正在运行的线程,并将结果放入Dictionary中。

using System; 使用系统; using System.Collections.Generic; 使用System.Collections.Generic; using System.Linq; 使用System.Linq; using System.Text; 使用System.Text; using System.Threading; 使用System.Threading; using System.Timers; 使用System.Timers;

namespace ConsoleApplication1 { class Program { static Dictionary threadResults = new Dictionary(); 命名空间ConsoleApplication1 {类Program {静态Dictionary threadResults = new Dictionary(); static int threadMax = 2; 静态int threadMax = 2;

    static void Main(string[] args)
    {
        List<Thread> runningThreads = new List<Thread>();
        for (int i = 0; i < threadMax; i++)
        {
            Worker worker = new Worker();
            worker.Callback = new Worker.CallbackDelegate(ThreadDone);
            Thread workerThread = new Thread(worker.DoSomething);
            workerThread.IsBackground = true;
            runningThreads.Add(workerThread);
            workerThread.Start();
        }

        foreach (Thread thread in runningThreads) thread.Join();
    }

    public static void ThreadDone(int threadIdArg, object resultsArg)
    {
        threadResults[threadIdArg] = resultsArg;
    }
}


class Worker
{
    public delegate void CallbackDelegate(int threadIdArg, object resultArg);
    public CallbackDelegate Callback { get; set; }
    public void DoSomething()
    {
        // do your thing and put it into results
        object results = new object();
        int myThreadId = Thread.CurrentThread.ManagedThreadId;
        Callback(myThreadId, results);
    }
}

} }

Try this on MSDN: "Asynchronous programming using delegates." 在MSDN上尝试以下操作:“使用委托进行异步编程”。

http://msdn.microsoft.com/en-us/library/22t547yb.aspx http://msdn.microsoft.com/en-us/library/22t547yb.aspx

-Oisin -Oisin

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM