如何在带有参数的线程中调用该方法并返回一些值

时间:2010-04-15 05:38:39

标签: c# multithreading method-call

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

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;
}

然后如何在线程中调用它?

7 个答案:

答案 0 :(得分:24)

您应该能够使用匿名方法或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
});

答案 1 :(得分:7)

这可能是另一种方法。这里输入作为参数化传递,并且在委托事件中传递返回类型,这样当线程完成时将调用Delegate。当线程完成时,这将很好地获得结果。

 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);
        }
    }

答案 2 :(得分:7)

我喜欢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);

答案 3 :(得分:1)

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

// 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);

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

答案 4 :(得分:0)

您可以在Thread构造函数上使用ParameterizedThreadStart重载。它允许您将Object作为参数传递给线程方法。它将是一个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;
}

答案 5 :(得分:0)

对于某些替代方案;钻营:

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));

或编写自己的捕获类型(这与编译器为您使用带有捕获变量的anon-methods / lambdas时的操作大致相当,但实现方式不同):

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

答案 6 :(得分:0)

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