Returning a value from thread?

前端 未结 17 2202
不思量自难忘°
不思量自难忘° 2020-11-27 09:45

How do I return a value from a thread?

相关标签:
17条回答
  • 2020-11-27 10:38

    ThreadStart delegates in C# used to start threads have return type 'void'.

    If you wish to get a 'return value' from a thread, you should write to a shared location (in an appropriate thread-safe manner) and read from that when the thread has completed executing.

    0 讨论(0)
  • 2020-11-27 10:40

    A simple solution is to pass a parameter by ref to the function that is running in the thread and change its value in the thread.

           // create a list of threads
            List<Thread> threads = new List<Thread>();
    
    
            //declare the ref params
            bool is1 = false;
            bool is2 = false;
    
            threads.Add(new Thread(() => myFunction(someVar, ref is1)));
            threads.Add(new Thread(() => myFunction(someVar, ref is2)));
    
            threads.ForEach(x => x.Start());
    
            // wait for threads to finish
            threads.ForEach(x => x.Join());
    
            //check the ref params
            if (!is1)
            {
              //do something
            }
    
            if (!is2)
            {
               //do somethign else
            }
    

    If you can't change the function that is running in the tread, you can wrap it another function:

     bool theirFunction(var someVar){
       return false;
    }
    
    
     void myFunction(var someVar ref bool result){
      result = theirFunction(myVar);
     }
    
    0 讨论(0)
  • 2020-11-27 10:42

    I'm no kind of expert in threading, that's why I did it like this:

    I created a Settings file and

    Inside the new thread:

    Setting.Default.ValueToBeSaved;
    Setting.Default.Save();
    

    Then I pick up that value whenever I need it.

    0 讨论(0)
  • 2020-11-27 10:43

    It depends on how do you want to create the thread and available .NET version:

    .NET 2.0+:

    A) You can create the Thread object directly. In this case you could use "closure" - declare variable and capture it using lambda-expression:

    object result = null;
    Thread thread = new System.Threading.Thread(() => { 
        //Some work...
        result = 42; });
    thread.Start();
    thread.Join();
    Console.WriteLine(result);
    

    B) You can use delegates and IAsyncResult and return value from EndInvoke() method:

    delegate object MyFunc();
    ...
    MyFunc x = new MyFunc(() => { 
        //Some work...
        return 42; });
    IAsyncResult asyncResult = x.BeginInvoke(null, null);
    object result = x.EndInvoke(asyncResult);
    

    C) You can use BackgroundWorker class. In this case you could use captured variable (like with Thread object) or handle RunWorkerCompleted event:

    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += (s, e) => {
        //Some work...
        e.Result = 42;
    };
    worker.RunWorkerCompleted += (s, e) => {
        //e.Result "returned" from thread
        Console.WriteLine(e.Result);
    };
    worker.RunWorkerAsync();
    

    .NET 4.0+:

    Starting with .NET 4.0 you could use Task Parallel Library and Task class to start your threads. Generic class Task<TResult> allows you to get return value from Result property:

    //Main thread will be blocked until task thread finishes
    //(because of obtaining the value of the Result property)
    int result = Task.Factory.StartNew(() => {
        //Some work...
        return 42;}).Result;
    

    .NET 4.5+:

    Starting with .NET 4.5 you could also use async/await keywords to return value from task directly instead of obtaining Result property:

    int result = await Task.Run(() => {
        //Some work...
        return 42; });
    

    Note: method, which contains the code above shoud be marked with asynckeyword.

    For many reasons using of Task Parallel Library is preferable way of working with threads.

    0 讨论(0)
  • 2020-11-27 10:43

    I would use the BackgroundWorker approach and return the result in e.Result.

    EDIT:

    This is commonly associated with WinForms and WPF, but can be used by any type of .NET application. Here's sample code for a console app that uses BackgroundWorker:

    using System;
    using System.Threading;
    using System.ComponentModel;
    using System.Collections.Generic;
    using System.Text;
    
    namespace BGWorker
    {
        class Program
        {
            static bool done = false;
    
            static void Main(string[] args)
            {
                BackgroundWorker bg = new BackgroundWorker();
                bg.DoWork += new DoWorkEventHandler(bg_DoWork);
                bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
                bg.RunWorkerAsync();
    
                while (!done)
                {
                    Console.WriteLine("Waiting in Main, tid " + Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(100);
                }
            }
    
            static void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                Console.WriteLine("Completed, tid " + Thread.CurrentThread.ManagedThreadId);
                done = true;
            }
    
            static void bg_DoWork(object sender, DoWorkEventArgs e)
            {
                for (int i = 1; i <= 5; i++)
                {
                    Console.WriteLine("Work Line: " + i + ", tid " + Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(500);
                }
            }
        }
    }
    

    Output:

    Waiting in Main, tid 10
    Work Line: 1, tid 6
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Work Line: 2, tid 6
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Work Line: 3, tid 6
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Work Line: 4, tid 6
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Work Line: 5, tid 6
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Waiting in Main, tid 10
    Completed, tid 6
    

    2014 UPDATE

    See @Roger's answer below.

    https://stackoverflow.com/a/24916747/141172

    He points out that you can use a Task that returns a Task<T>, and check Task<T>.Result.

    0 讨论(0)
提交回复
热议问题