Pergunta

I have the following function and I'd like to use it within a System.Threading.Thread :

private void tempFunction(int num, out string fullname, out string info)
{
    // Doing a very long scenario.
    // When finished, send results out!
    fullname = result1;
    info = result2;
}

I've tried to use the following code in (button_Click) event handler :

private void submit_Button_Click(object sender, RoutedEventArgs e)
{
    string Fullname = string.Empty, Info = string.Empty;
    int index = 132;

    Thread thread = new Thread(() => tempFunction(index, out Fullname, out Info));
    thread.Start();
    thread.Join();

    // I always use "MessageBox" to check if what I want to do was done successfully
    MessageBox.Show(Fullname + "\n" + Info);
}

You can see that I use thread.Join(); because I need to wait untill the Thread finishes to get the result of the threaded process.

But the code above seems not working, it just freezes and I don't know why!

So I'm definitely doing something wrong, can you tell me how to do what I want?

Foi útil?

Solução

The fact that the program freezes doesn't have anything to do with the out parameter.

The program freezes because you call Thread.Join() which basically reads: "block the calling thread until I finish processing". Because the calling thread is the UI thread, the UI freezes.

There are a number of ways to solve this problem, the most appealing of which is to use the await keyword (C# 5) but given the dependency on NET 4.5, you may opt to attach a continuation manually instead:

Task.Factory.StartNew(() => tempFunction(index, out Fullname, out Info))
            .ContinueWith(r => MessageBox.Show(Fullname + "\n" + Info));

(You are going to need to target .NET 4.0 in order to use the Task class.)

If you are limited to an earlier version of the framework then the next best solution will likely be to use the BackgroundWorker component given that you appear to be working with a Windows Forms application.

Outras dicas

This code will freeze the UI until the code completes because of the join statement. This statement tells the current thread, which in this case is the UI thread to block for the completion of the worker thread. After completion of the join, the message box will show.

Use the Task class as already suggested or the new async/await constructs. But, if you are using an older version of the framework, you can use the following

 delegate void TempFunctionDelegate(int num, out string fullname, out string info);

    private void tempFunction(int num, out string fullname, out string info)
    {
        /*do something for a long time*/
        Thread.Sleep(5000);
        fullname = "result1";
        info = "result2";
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        string Fullname = string.Empty, Info = string.Empty;
        int index = 132;

        TempFunctionDelegate tempFunctionDelegate = tempFunction;
        tempFunctionDelegate.BeginInvoke(index, out Fullname, out Info, CallBackToUI, tempFunctionDelegate);

    }

    void CallBackToUI(IAsyncResult ar)
    {
        var tempFunctionDelegate = ar.AsyncState as TempFunctionDelegate;
        string fullName = null;
        string info = null;
        tempFunctionDelegate.EndInvoke(out fullName, out info, ar);

        MessageBox.Show(fullName + "\n" + info);
    }

If i correctly understand the problem, it's the freeze. For me the problem is the usage of the Thread instead of a BackgroundWorker. The second one will allow the UI events to continue to be processed.

Would this work for you?

Thread th = new Thread(() =>
{
    tempfunction(index, out fullname, out info);
    MessageBox.Show(fullname + ":" + info);
});
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top