方法执行完毕后从线程获取变量

时间:2014-04-17 15:28:55

标签: c# multithreading

目前我有一个名为Worker的类,方法DoWork将字符串发送到服务器,然后服务器返回一个字符串。

class Worker
{

      public Worker(int id)
      {
           //Stuff
      }

      public string DoWork(string s)
      {
            //Manipulate s

            return s;
      }
}

现在我想要实现的是让多个线程工作者运行DoWork方法并检索第一个方法的值以返回s字符串,然后关闭所有线程。

这是迄今为止我所得到的:

class Program
{
        public string DoWork(string s);

        static void Main(string[] args)
        {
            string s = "String";
            Worker w1 = new Worker(1);
            Worker w2 = new Worker(2);
            Worker w3 = new Worker(3);

                Thread t1 = new Thread(() => w1.DoWork(s));
                Thread t2 = new Thread(() => w2.DoWork(s));
                Thread t3 = new Thread(() => w3.DoWork(s));
                t1.Start();
                t2.Start();
                t3.Start();
        }
}

目前该程序无法编译,我收到错误:

  

DoWork(字符串)必须声明一个正文,因为它没有标记为abstract,extern或partial

我也不确定如何检索字符串(我只想要第一个返回的值)。

我想要实现的目标是什么?

3 个答案:

答案 0 :(得分:1)

您应该从DoWork中删除Program声明以删除编译错误。

此外,如果您希望线程将值返回到主线程,并且如果您使用的是.NET 4 / 4.5,请考虑使用Task<T>,而不是直接使用线程。任务会更好地为你服务。

Task<string> task1 = Task.Run(() => w1.DoWork(s));


//non-blocking
string result1 = await task1;

//or

//blocking call, "equivalent" of "thread.Join()"
string result1 = task1.Result;

答案 1 :(得分:0)

您还可以使用委托进行异步调用:

public delegate string AsyncWorkCaller(string s);

以及执行它的代码:

Worker w = new Worker(0);
AsyncWorkCaller caller = new AsyncWorkCaller(w.DoWork);

string s = "your string";
caller.BeginInvoke(s, WorkCallback, null);

和回调方法:

private void WorkCallback(IAsyncResult ar)
{
    AsyncResult result = (AsyncResult)ar;
    AsyncWorkCaller caller = (AsyncWorkCaller)result.AsyncDelegate;

    string returnValue = caller.EndInvoke(ar);

    //manipulate the new s value here
 }

http://msdn.microsoft.com/en-us/library/2e08f6yc%28v=vs.110%29.aspx

答案 2 :(得分:0)

如果您使用任务并行库而不是原始任务,则可以使用Task.WaitAny非常有效地解决此问题。

string s = "String";

var tasks = Enumerable.Range(0, 3)
    .Select(i => Task.Run(()=> new Worker(i).DoWork(s)))
    .ToArray();

var finishedindex = Task.WaitAny(tasks);
Console.WriteLine(tasks[finishedindex].Result);