简体   繁体   中英

How to Get a result from a method on another thread in c#

I am very confused here and not sure if the framework (4.0) supports some of the answers I found so far online.

I have the following structure

public class Form1() 
{

    public int GenerateID(OtherThreadObj oto)
    {
       int result;
       if (this.InvokeRequired)
                {
                    return (int)this.Invoke((MethodInvoker)delegate { GenerateIDSafe(oto); });
                // now this doesn't work obviously. I was looking at .begininvoke, end, etc and got really lost there

                }
                else
                {
               return   GenerateIDSafe(oto);
                }
    }


    private int GenerateIDSafe(OtherThreadObj oto)
    {

    return oto.id.ToSuperID(); // Assume ToSuperID some extension method.

    }

    }

Now the Idea is to call The Generate ID from another Thread and get that return value.

    public class OtherThreadObj 
    {

    private Form1 parentform;

    private int GetSuperID()
    {

    return parentform.GenerateID(this);

    }
    }

so obviously the above is no good because I don't get the right return on the .Invoke. I am totally lost on how to do this properly.

You were almost there:

public int GenerateID(OtherThreadObj oto)
{
    int result;
    this.Invoke((MethodInvoker)delegate { result = GenerateIDSafe(oto); });
    return result;
}

Use callback functions or delegates. This is a function you pass to another function to call once async processing is done.

In the example below GetMeValue calls GetValue asynchronously and GotTheValue is used for callback. A better way to organize things would be to pass the callback directly to GetValue and have it run asynchronously. This is the case with networking in Silverlight for example if you're looking for better examples.

An even better approach would be to learn about the "async" operator in C#

public class Producer{ 
    public static int GetValue(){
    //... long running operation
    }
}


public class FormConsumer{


   public void GetMeValue(){
       int v = 0;
       // setting up for async call
       Action asyncCall = () => { v = Producer.GetValue();};

       // this is the delegate that will be called when async call is done
       AsyncCallback = (acbk)=> {
            this.Invoke((MethodInvoker)delegate{ 
                GotTheValue(v)
            });
       };

       // execute the call asynchronously
       asyncCall.BeginInvoke(acbk, null); 
   }

   public void GotTheValue(int v){
     // this gets called on UI thread 
   }
}

In .net 4.0 you can use the Task Parallel Library (TPL) this makes muti-threading a lot easier than the previous paradigms. The code below runs the method "GenerateID" on a different thread. Then i get the result and display it on my main thread.

using System.Threading.Tasks;

namespace Console
{
    class Program
    {
        static void Main(string[] args)
        {
            Task<int> task = Task<int>.Factory.StartNew(() =>
                {
                    return GenerateID();
                 });

            int result = task.Result;

            System.Console.WriteLine(result.ToString());

            System.Console.ReadLine();
        }

        static private int GenerateID()
        {
            return 123;
        }
    }
}

Hope this helps.

Or another example to make it clear:

void do_access ()
{
   if (ctrl.InvokeRequired) {      
      ctrl.Invoke (new MethodInvoker (do_access));
      return;
   }
   ctrl.Text = "Hello World!";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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