我有一些代码,我需要运行在不同的线程,而不是GUI,因为它目前导致窗体冻结,而代码运行(10秒左右)。

假设我以前从未创建过一个新线程;有什么简单/基本的例子,如何做到这一点在c#和使用。net Framework 2.0或更高版本?


当前回答

我建议参考Jeff Richter的Power Threading Library,特别是IAsyncEnumerator。看看查理·卡尔弗特博客上的视频,里希特对它有一个很好的概述。

不要被这个名字吓倒,因为它使异步编程任务更容易编码。

其他回答

将该代码放入一个函数中(不能与GUI在同一个线程上执行的代码),并执行以下代码来触发该代码的执行。

线程myThread=新线程(namefunction);

workerThread.Start();

在线程对象上调用start函数将导致在新线程中执行函数调用。

BackgroundWorker似乎是您的最佳选择。

下面是我的最小示例。在你点击按钮后,后台工作人员将开始在后台线程工作,并同时报告其进度。它也将在工作完成后报告。

using System.ComponentModel;
...
    private void button1_Click(object sender, EventArgs e)
    {
        BackgroundWorker bw = new BackgroundWorker();

        // this allows our worker to report progress during work
        bw.WorkerReportsProgress = true;

        // what to do in the background thread
        bw.DoWork += new DoWorkEventHandler(
        delegate(object o, DoWorkEventArgs args)
        {
            BackgroundWorker b = o as BackgroundWorker;

            // do some simple processing for 10 seconds
            for (int i = 1; i <= 10; i++)
            {
                // report the progress in percent
                b.ReportProgress(i * 10);
                Thread.Sleep(1000);
            }

        });

        // what to do when progress changed (update the progress bar for example)
        bw.ProgressChanged += new ProgressChangedEventHandler(
        delegate(object o, ProgressChangedEventArgs args)
        {
            label1.Text = string.Format("{0}% Completed", args.ProgressPercentage);
        });

        // what to do when worker completes its task (notify the user)
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
        delegate(object o, RunWorkerCompletedEventArgs args)
        {
            label1.Text = "Finished!";
        });

        bw.RunWorkerAsync();
    }

注意:

我把所有东西都放在一个方法里 使用c#的匿名方法 简单但你总是可以拉 他们想出了不同的方法。 在里面更新GUI是安全的 ProgressChanged或 RunWorkerCompleted处理程序。 但是,从DoWork更新GUI 将会导致 InvalidOperationException。

ThreadPool。QueueUserWorkItem对于简单的东西来说是非常理想的。唯一需要注意的是从另一个线程访问控件。

System.Threading.ThreadPool.QueueUserWorkItem(delegate {
    DoSomethingThatDoesntInvolveAControl();
}, null);

如果你打算使用原始线程对象,那么你需要将IsBackground设置为true,你还应该设置Threading Apartment模型(可能是STA)。

public static void DoWork()
{
    // do some work
}

public static void StartWorker()
{
    Thread worker = new Thread(DoWork);
    worker.IsBackground = true;
    worker.SetApartmentState(System.Threading.ApartmentState.STA);
    worker.Start()
}

如果你需要UI交互,我会推荐BackgroundWorker类。

我建议参考Jeff Richter的Power Threading Library,特别是IAsyncEnumerator。看看查理·卡尔弗特博客上的视频,里希特对它有一个很好的概述。

不要被这个名字吓倒,因为它使异步编程任务更容易编码。