【问题标题】:How to call the method in thread with arguments and return some value如何在带参数的线程中调用方法并返回一些值
【发布时间】:2010-04-15 05:38:39
【问题描述】:

我喜欢在线程中调用带有参数的方法并在此处返回一些值示例

class Program
{
    static void Main()
    {
        Thread FirstThread = new Thread(new ThreadStart(Fun1));
        Thread SecondThread = new Thread(new ThreadStart(Fun2));
        FirstThread.Start();
        SecondThread.Start();
    }
    public static void Fun1()
    {
        for (int i = 1; i <= 1000; i++)
        {
            Console.WriteLine("Fun1 writes:{0}", i);
        }
    }
    public static void Fun2()
    {
        for (int i = 1000; i >= 6; i--)
        {
            Console.WriteLine("Fun2 writes:{0}", i);
        }
    }
}

我知道上面这个例子运行成功,但是如果方法 fun1 像这样

public int fun1(int i,int j)
{
    int k;
    k=i+j;
    return k;
}

那我如何在线程中调用它?

【问题讨论】:

  • 我觉得这些例子已经足够了。如果这个答案与您的期望不符,那么请给出完整的场景和您需要的内容。

标签: c# multithreading method-call


【解决方案1】:

您应该能够使用匿名方法或 lambda 来提供完整的静态检查:

Thread FirstThread = new Thread(() => Fun1(5, 12));

或者如果你想对结果做点什么:

Thread FirstThread = new Thread(() => {
    int i = Fun1(5, 12);
    // do something with i
});

但请注意,这个“做某事”仍然在新线程的上下文中运行(但可以访问外部方法中的其他变量 (Main),由“捕获的变量”提供)。

如果你有 C# 2.0(而不是更高版本),那么:

Thread FirstThread = new Thread((ThreadStart)delegate { Fun1(5, 12); });

Thread FirstThread = new Thread((ThreadStart)delegate {
    int i = Fun1(5, 12);
    // do something with i
});

【讨论】:

  • @ratty - 你到底想要什么?
【解决方案2】:

这可能是另一种方法。这里输入作为参数化线程传递,返回类型在委托事件中传递,因此当线程完成时将调用委托。线程完成后就可以得到结果了。

 public class ThreadObject
    {
        public int i;
        public int j;
        public int result;
        public string Name;
    }



    public delegate void ResultDelegate(ThreadObject threadObject);

    public partial class Form1 : Form
    {

        public event ResultDelegate resultDelete;

        public Form1()
        {
            InitializeComponent();

            resultDelete += new ResultDelegate(resultValue);
        }

        void resultValue(ThreadObject threadObject)
        {
            MessageBox.Show("Thread Name : " + threadObject.Name + " Thread Value : " + threadObject.result);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ThreadObject firstThreadObject = new ThreadObject();
            firstThreadObject.i = 0;
            firstThreadObject.j = 100;
            firstThreadObject.Name = "First Thread";

            Thread firstThread = new Thread(Fun);
            firstThread.Start(firstThreadObject);


            ThreadObject secondThreadObject = new ThreadObject();
            secondThreadObject.i = 0;
            secondThreadObject.j = 200;
            secondThreadObject.Name = "Second Thread";

            Thread secondThread = new Thread(Fun);
            secondThread.Start(secondThreadObject);

        }


        private void Fun(object parameter)
        {
            ThreadObject threadObject = parameter as ThreadObject;

            for (; threadObject.i < threadObject.j; threadObject.i++)
            {
                threadObject.result += threadObject.i;

                Thread.Sleep(10);
            }

            resultValue(threadObject);
        }
    }

【讨论】:

    【解决方案3】:

    我喜欢 Mark Gravell 的回答。您只需稍作修改即可将结果传回主线程:

    int fun1, fun2;
    Thread FirstThread = new Thread(() => {
        fun1 = Fun1(5, 12);
    });
    Thread SecondThread = new Thread(() => {
        fun2 = Fun2(2, 3); 
    });
    
    FirstThread.Start();
    SecondThread.Start();
    FirstThread.Join();
    SecondThread.Join();
    
    Console.WriteLine("Fun1 returned {0}, Fun2 returned {1}", fun1, fun2);
    

    【讨论】:

      【解决方案4】:

      在单独的线程中执行函数有更简单的方法:

      // Create function delegate (it can be any delegate)
      var FunFunc = new Func<int, int, int>(fun1);
      // Start executing function on thread pool with parameters
      IAsyncResult FunFuncResult = FunFunc.BeginInvoke(1, 5, null, null);
      // Do some stuff
      // Wait for asynchronous call completion and get result
      int Result = FunFunc.EndInvoke(FunFuncResult);
      

      此函数将在线程池线程上执行,并且该逻辑对您的应用程序是完全透明的。 一般来说,我建议在线程池而不是专用线程上执行这样的小任务。

      【讨论】:

        【解决方案5】:

        您可以在 Thread 构造函数上使用 ParameterizedThreadStart 重载。它允许您将对象作为参数传递给您的线程方法。这将是一个单独的Object参数,所以我通常为这样的线程创建一个参数类。这个对象还可以存储线程执行的结果,你可以在线程结束后读取。

        不要忘记在线程运行时访问该对象是可能的,但不是“线程安全的”。你知道演习:)

        这是一个例子:

        void Main()
        {
            var thread = new Thread(Fun);
            var obj = new ThreadObject
            {
                i = 1,
                j = 15,
            };
        
            thread.Start(obj);
            thread.Join();
            Console.WriteLine(obj.result);
        }
        
        public static void Fun(Object obj)
        {
            var threadObj = obj as ThreadObject;
            threadObj.result = threadObj.i + threadObj.j;
        }
        
        public class ThreadObject
        {
            public int i;
            public int j;
            public int result;
        }
        

        【讨论】:

          【解决方案6】:

          对于一些替代品;柯里化:

          static ThreadStart CurryForFun(int i, int j)
          { // also needs a target object if Fun1 not static
              return () => Fun1(i, j);
          }
          
          Thread FirstThread = new Thread(CurryForFun(5, 12));
          

          或编写您自己的捕获类型(这与您使用带有捕获变量的非方法/lambda 时编译器为您所做的大致相当,但实现方式不同):

          class MyCaptureClass
          {
              private readonly int i, j;
              int? result;
              // only available after execution
              public int Result { get { return result.Value; } }
              public MyCaptureClass(int i, int j)
              {
                  this.i = i;
                  this.j = j;
              }
              public void Invoke()
              { // will also need a target object if Fun1 isn't static
                  result = Fun1(i, j);
              }
          }
          ...
          MyCaptureClass capture = new MyCaptureClass(5, 12);
          Thread FirstThread = new Thread(capture.Invoke);
          // then in the future, access capture.Result
          

          【讨论】:

            【解决方案7】:

            尝试使用 backgroundWorker http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx 您可以使用 DoWorkEventArgs 将值传递给 DoWork 事件,并在 RunWorkerCompleted 中检索值。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-04-01
              • 1970-01-01
              • 2015-10-14
              • 2014-09-19
              • 1970-01-01
              • 2012-08-05
              相关资源
              最近更新 更多