4

我有以下功能,我想在 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;
}

我尝试在 (button_Click) 事件处理程序中使用以下代码:

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

你可以看到我使用thread.Join();的是因为我需要等到线程完成才能获得线程进程的结果。

但是上面的代码似乎不起作用,它只是冻结了,我不知道为什么!

所以我肯定做错了什么,你能告诉我如何做我想做的事吗?

4

4 回答 4

13

程序冻结的事实与out参数无关。

程序冻结,因为您调用Thread.Join()它基本上读取:“阻塞调用线程直到我完成处理”。因为调用线程是 UI 线程,所以 UI 会冻结。

有很多方法可以解决这个问题,其中最吸引人的是使用 await关键字 (C# 5),但鉴于对 NET 4.5 的依赖,您可以选择手动附加延续:

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

(您需要以 .NET 4.0 为目标才能使用Task该类。)

如果您受限于较早版本的框架,那么下一个最佳解决方案可能是使用该BackgroundWorker组件,因为您似乎正在使用 Windows 窗体应用程序。

于 2013-08-11T01:50:07.243 回答
2

由于 join 语句,此代码将冻结 UI 直到代码完成。该语句告诉当前线程,在这种情况下是 UI 线程为完成工作线程而阻塞。加入完成后,将显示消息框。

使用已经建议的 Task 类或新的 async/await 构造。但是,如果您使用的是旧版本的框架,则可以使用以下

 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);
    }
于 2013-08-11T02:32:06.807 回答
0

如果我正确理解了这个问题,那就是冻结。对我来说,问题是使用 Thread 而不是BackgroundWorker。第二个将允许继续处理 UI 事件。

于 2013-08-11T01:50:45.130 回答
0

这对你有用吗?

Thread th = new Thread(() =>
{
    tempfunction(index, out fullname, out info);
    MessageBox.Show(fullname + ":" + info);
});
于 2013-08-11T02:08:18.420 回答