4

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?

Alaa Salah
  • 885
  • 1
  • 13
  • 23
  • 1
    Eliminate the easy problems first. Have you tried running it without a thread? Does it finish? – Zan Lynx Aug 11 '13 at 01:45
  • 4
    Another issue here: When you start a thread and immediately join it you may as well have just called the function. Nothing is being done asynchronously here. – Zan Lynx Aug 11 '13 at 01:46
  • @ZanLynx It works perfectly without a Thread, but actually I don't know how to use this kind of function with a thread. No problem at all with that function, the main issue is with the thread. – Alaa Salah Aug 11 '13 at 01:47
  • @ZanLynx Ok what should I do to wait untill the thread finishes so I can get the results back ? I know nothing except using `Join()` and I haven't tried it before. – Alaa Salah Aug 11 '13 at 01:50
  • @AlaaJoseph - that is exactly the point being made by other commenters - if you have to wait, there is no point. – Martin James Aug 11 '13 at 08:26

4 Answers4

13

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.

User 12345678
  • 7,714
  • 2
  • 28
  • 46
  • 1
    If you are going to be using .net 4.0 you can still use Async/await, just download it the [BCL update from nuget](http://www.nuget.org/packages/Microsoft.Bcl.Async). – Scott Chamberlain Aug 11 '13 at 01:55
  • 1
    If (as it appears) the OP is using ASP.NET, could this cause the opposite problem, *viz*, that the request will complete and forget about the other thread? – harpo Aug 11 '13 at 01:55
  • Aaarghh! Join() again. All the other possible means of inter-thread comms, queues, messages, tasks, and soddin' Join(), probably the worst possible choice, is the first method taught on 'Thread 101' sites/pages. Dreck! – Martin James Aug 11 '13 at 08:30
  • This is a simple and easy-to-use solution, thank you so much. – Alaa Salah Aug 11 '13 at 13:52
2

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);
    }
  • This is the perfect choice when my projects target a version older than 4.0 of the framework, thanks a lot. – Alaa Salah Aug 11 '13 at 13:54
0

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.

Emmanuel Istace
  • 1,209
  • 2
  • 14
  • 32
0

Would this work for you?

Thread th = new Thread(() =>
{
    tempfunction(index, out fullname, out info);
    MessageBox.Show(fullname + ":" + info);
});
Nilesh
  • 2,583
  • 5
  • 21
  • 34