C# WinForm多线程。是否使用backgroundWorker?

C# WinForm多线程。是否使用backgroundWorker?,c#,winforms,multithreading,C#,Winforms,Multithreading,我有一个简单的应用程序,可以启动一系列数据密集型任务。我对WinForms不是很有经验,我想知道不锁定接口的最佳方法。backgroundWorker是否可以重复使用,或者是否有其他方法可以重复使用 谢谢背景工作者将是一个很好的选择 有关更多信息,请查看此处 可以使用backgroundWorker 它的好处是允许您更新进度条并与UI控件交互。(WorkerReportsProgress) 它还有一个取消机制。(工人支持扫描单元) BackgroundWorker是一个线程,它还包括通知同步。例

我有一个简单的应用程序,可以启动一系列数据密集型任务。我对WinForms不是很有经验,我想知道不锁定接口的最佳方法。backgroundWorker是否可以重复使用,或者是否有其他方法可以重复使用


谢谢

背景工作者将是一个很好的选择

有关更多信息,请查看此处
可以使用backgroundWorker

它的好处是允许您更新进度条并与UI控件交互。(
WorkerReportsProgress

它还有一个取消机制。(
工人支持扫描单元


BackgroundWorker是一个线程,它还包括通知同步。例如,如果您想在扫描完成时更新UI,常规的
线程
无法访问UI对象(只有UI线程可以这样做);因此,
BackgroundWorker
提供了一个完整的事件处理程序,在操作完成时在UI线程上运行

有关更多信息,请参阅:(MSDN)

和一个简单的示例代码:

var worker = new System.ComponentModel.BackgroundWorker();
worker.DoWork += (sender,e) => Thread.Sleep(60000);
worker.RunWorkerCompleted += (sender,e) => MessageBox.Show("Hello there!");
worker.RunWorkerAsync();

您可以使用BackgroundWorker来满足这些需求。下面是一个示例,
根据任务[长时间运行]完成的百分比更新标签状态
。另外,还有一个示例业务类,它设置了一些值,该值通过
ProgressChanged
handler设置回UI
DoWork
是编写长时间运行的任务逻辑的地方。在Winforms应用程序上添加标签和backgroundworker组件后,复制粘贴下面的代码并试一试。您可以跨各种处理程序
[RunWorkerCompleted,ProgressChanged,DoWork]
进行调试,并查看
InitWorker
方法。请注意
取消功能

using System.ComponentModel;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form3 : Form
    {
        private BackgroundWorker _worker;
        BusinessClass _biz = new BusinessClass();
        public Form3()
        {
            InitializeComponent();
            InitWorker();
        }

        private void InitWorker()
        {
            if (_worker != null)
            {
                _worker.Dispose();
            }

            _worker = new BackgroundWorker
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };
            _worker.DoWork += DoWork;
            _worker.RunWorkerCompleted += RunWorkerCompleted;
            _worker.ProgressChanged += ProgressChanged;
            _worker.RunWorkerAsync();
        }


        void DoWork(object sender, DoWorkEventArgs e)
        {
            int highestPercentageReached = 0;
            if (_worker.CancellationPending)
            {
                e.Cancel = true;
            }
            else
            {
                double i = 0.0d;
                int junk = 0;
                for (i = 0; i <= 199990000; i++)
                {
                    int result = _biz.MyFunction(junk);
                    junk++;

                    // Report progress as a percentage of the total task.
                    var percentComplete = (int)(i / 199990000 * 100);
                    if (percentComplete > highestPercentageReached)
                    {
                        highestPercentageReached = percentComplete;
                        // note I can pass the business class result also and display the same in the LABEL  
                        _worker.ReportProgress(percentComplete, result);
                        _worker.CancelAsync();
                    }
                }

            }
        }

        void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                // Display some message to the user that task has been
                // cancelled
            }
            else if (e.Error != null)
            {
                // Do something with the error
            }
        }

        void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label1.Text =  string.Format("Result {0}: Percent {1}",e.UserState, e.ProgressPercentage);
        }
    }

    public class BusinessClass
    {
        public int MyFunction(int input)
        {
            return input+10;
        }
    }
}
使用System.ComponentModel;
使用System.Windows.Forms;
命名空间Windows窗体应用程序1
{
公共部分类表单3:表单
{
私人背景工人;
BusinessClass _biz=新的BusinessClass();
公共表格3()
{
初始化组件();
InitWorker();
}
私有void InitWorker()
{
如果(_worker!=null)
{
_worker.Dispose();
}
_worker=新的后台工作人员
{
WorkerReportsProgress=true,
WorkerSupportsScanCellation=真
};
_worker.DoWork+=DoWork;
_worker.RunWorkerCompleted+=RunWorkerCompleted;
_worker.ProgressChanged+=ProgressChanged;
_worker.RunWorkerAsync();
}
无效DoWork(对象发送方,DoWorkEventArgs e)
{
int highestPercentageReached=0;
如果(_worker.CancellationPending)
{
e、 取消=真;
}
其他的
{
双i=0.0d;
int=0;
对于(i=0;i最高百分比)
{
highestPercentageReached=完成百分比;
//注意,我也可以传递业务类结果,并在标签中显示相同的结果
_工人报告进度(完成百分比、结果);
_worker.CancelAsync();
}
}
}
}
void RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
如果(如已取消)
{
//向用户显示任务已完成的消息
//取消
}
否则如果(例如错误!=null)
{
//对这个错误做点什么
}
}
void ProgressChanged(对象发送方,progresschangedventargs e)
{
label1.Text=string.Format(“结果{0}:百分比{1}”,e.UserState,e.ProgressPercentage);
}
}
公务舱
{
公共整数MyFunction(整数输入)
{
返回输入+10;
}
}
}

我会使用backgroundworker。如果您只需要另外一个线程,我会使用后台工作线程,它们非常容易使用,而且大部分的艰苦工作已经完成,为您提供工作完成不同阶段的直接事件。如果您需要该线程在完成其密集工作后与UI元素交互,请使用Backgroundworker。另一个明智的做法是,如果你只是想做一些其他的工作,例如从其他地方填充一些容器数据,这些数据在其他时间或事件中由主UI使用,那么就使用普通线程。用户可以启动各种不同的任务,然后通过entityFramework执行数据库操作。那么,当用户完成任务A后,backgroundworker是否可以再次用于任务B?感谢您的详细回复。我关心的是将“长时间运行的任务逻辑”添加到DoWork事件中。我有许多任务需要运行,将它们全部添加到一个DoWork事件中似乎不太实际。