C# 控制繁忙GUI的最佳实践

C# 控制繁忙GUI的最佳实践,c#,delegates,C#,Delegates,假设一个GUI(C#,WinForms)执行工作并忙碌几秒钟。它仍然有需要保持可访问的按钮、将更改的标签、进度条等 我目前正在使用这种方法在繁忙时更改GUI: //Generic delegates private delegate void SetControlValue<T>(T newValue); //... public void SetStatusLabelMessage(string message) { if (StatusLabel.InvokeRequi

假设一个GUI(C#,WinForms)执行工作并忙碌几秒钟。它仍然有需要保持可访问的按钮、将更改的标签、进度条等

我目前正在使用这种方法在繁忙时更改GUI:

//Generic delegates
private delegate void SetControlValue<T>(T newValue);

//...
public void SetStatusLabelMessage(string message)
{
    if (StatusLabel.InvokeRequired)
        StatusLabel.BeginInvoke(new SetControlValue<string>(SetStatusLabelMessage, object[] { message });
    else
        StatusLabel.Text = message;
}
//泛型委托
私有委托void SetControlValue(T newValue);
//...
公共无效SetStatusLabelMessage(字符串消息)
{
if(StatusLabel.InvokeRequired)
StatusLabel.BeginInvoke(新的SetControlValue(SetStatusLabelMessage,对象[]{message});
其他的
StatusLabel.Text=消息;
}

我一直在使用它,好像它已经过时了,但我不太确定这是否合适。创建委托(并重用它)使整个事情变得更干净(至少对我来说),但我必须知道,我并不是在创建怪物…

我觉得这是对的。只要您将这类东西封装到它自己经过良好测试的类中,它就不会有问题。

另一种选择是在需要更新GUI时使用and和use。这将为您处理调用,这样您就不必担心是的。

这里的最佳实践是使用BackgroundWorker来运行长时间运行的任务。这是一个专门为WinForms设置的特殊线程类,仅用于此目的。您可以将工作发送给它,取消它,还可以让它将消息发送回WinForm线程以更新状态。基本上,通过使用BackgroundWorker,您的GUI保持不变自由和活跃。

其他人提到使用BackgroundWorker来运行您的工作。这就是您正在做的吗

在任何情况下,如果您想知道从后台线程更新UI的最佳方式是什么,您所做的看起来都不错,尽管我建议使用
Invoke
而不是
BeginInvoke
。此外,您可以使用
MethodInvoker
来简化代码,而不是声明自己的单独委托:

StatusLabel.Invoke(new MethodInvoker(delegate() { /* Update control here */ }));

通过“进入自己的阶级”,你的意思是相对于表单类吗?我不赞成在表单类中塞满最多的代码,恰恰相反,但如果它控制表单,我有一个习惯,就是将其保留在表单类中。@MPelletier:我的意思是,将特定于UI实现的代码保留在应用程序和业务逻辑之外,而这些应用程序和业务逻辑本应已经存在分离到自己的类中。因此,实际上,将这些内容放在form类中是可以的。我很难协调BackgroundWorker和程序中使用的其他线程。作为一个经验丰富的绅士程序员,您更经常看到哪一个?通过BackgroundWorker控制还是调用?@MPelletier:BackgroundWorker用于此类任务-你有一个长时间运行的任务,你需要保持GUI响应,并且你需要显示一个进度条。这正是BackgroundWorker设计的目的。我想问的问题更多的是,“从后台线程更新UI的最佳实践是什么?”。这个答案并没有真正解决这个问题。没有使用BackgroundWorker,没有。如果BGW只调用一个线性函数,我会这样做,但在某些程序中后台函数使用线程池,我会犹豫。在这个级别上,我觉得我是在不必要地分层结构。感谢Invoke/BeginInvoke,wh我需要更新我的头脑,以便更好地理解其中的差异。MethodInvoker看起来也不错!没问题。这有助于回答您的问题,还是您在寻找其他东西?但他已经在做这件事了,尽管他使用的类与
BackgroundWorker
不同。他要求提供“最佳实践”BackgroundWorker是“最佳实践”