【发布时间】:2015-09-23 21:09:17
【问题描述】:
背景资料
我的主窗体实例名为“MainView”,包含以下内容:
- 名为
contentPanel的面板包含各种输入控件(包括childControl,它一开始是禁用的)。 - BackgroundWorker 控件。
backgroundWorker_DoWork(3-arg) 在单击提交按钮时被调用。 contentPanel 被禁用,因此用户在处理提交时无法进行更改、垃圾邮件按钮等。如果提交成功,还需要进行某些 UI 更改(在下面的问题部分中对此进行了详细说明)。
contentPanel相关代码
private void btnSubmit_Click(object sender, EventArgs e)
{
...
Type[] parameterTypes = new Type[] { suiteRel.GetType() };
MethodInfo method = this.GetType().GetMethod("btnSubmit_Click", parameterTypes);
mainView.backgroundWorker_DoWork(this, method, myData);
}
/// <summary>
/// Commits changes to the database.
///
/// Note: This method will be executed from a non-UI thread. As such
/// accessing or modifying UI controls must be done via an Invoke() call.
/// </summary>
public void btnSubmit_Click(Object myData)
{
...
if (success)
{
this.Invoke(new Action(
() => {
childControl.Enabled = true;
}
));
}
}
BackgroundWorker相关代码
/// <summary>
/// Starts another thread to perform a potentially long-running task (e.g. validation, database commits, etc).
/// </summary>
/// <param name="reference">
/// A reference to the control instance that owns the method to be called.
/// </param>
/// <param name="method">
/// The method to be called that will perform the work.
/// </param>
/// <param name="parameters">
/// Parameters to pass to the method when it is called.
/// </param>
public void backgroundWorker_DoWork(object reference, MethodInfo method, params object[] parameters)
{
List<object> methodAndArgs = new List<object>();
methodAndArgs.Add(reference);
methodAndArgs.Add(method);
methodAndArgs.Add(parameters);
contentPanel.Enabled = false;
this.UseWaitCursor = true;
backgroundWorker.RunWorkerAsync(methodAndArgs);
}
/// <summary>
/// Starting point of a worker thread (i.e. not on the UI thread).
/// </summary>
/// <param name="sender">
/// The object that initiated the work request.
/// </param>
/// <param name="e">
/// The arguments that dictate what work to do. In particular, e.Argument
/// contains the parameters passed to the public backgroundWorker_DoWork().
/// </param>
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
List<object> methodAndArgs = (List<object>)e.Argument;
object reference = methodAndArgs[0];
MethodInfo method = (MethodInfo)methodAndArgs[1];
object[] parameters = (object[])methodAndArgs[2];
// call method with its parameters.
// a.k.a. "method(param1, param2, ...);"
method.Invoke(reference, parameters);
}
/// <summary>
/// Called on the UI thread after backgroundWorker_DoWork() completes.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
contentPanel.Enabled = true;
this.UseWaitCursor = false;
}
问题
当在backgroundWorker_DoWork(2-arg) 中执行“方法”时,我将contentPanel 中的子控件的启用属性设置为true。目的是在调用backgroundWorker_RunWorkerCompleted() 时启用contentPanel 时将启用子控件。但是,在调用backgroundWorker_RunWorkerCompleted() 后,子控件仍然处于禁用状态。
我了解在禁用父控件的同时启用 的子控件是不可能的(例如,this question 要求的内容),这是不强> 我正在尝试做的事情。我希望在启用其父控件 (contentPanel) 时启用子控件(类似于在单击提交按钮之前启用的其他子控件在backgroundWorker_RunWorkerCompleted() 中启用contentPanel 时重新启用的方式)。
【问题讨论】:
-
你有一些奇怪的意大利面条代码,很难弄清楚你为什么要做你正在做的事情。我想简单的问题是,
success是真的吗?您没有很好地记录该变量。 -
@LarsTech 是的,
success通常是正确的。我已经使用断点来验证childControl.Enabled = true;确实被执行了。我选择这种架构是因为 (1) 我有一个长时间运行的提交过程,当在 UI 线程上执行时会导致应用程序挂起,直到提交完成,以及 (2) 我的应用程序中有多个面板都需要表现提交时相同。
标签: c# multithreading winforms c#-4.0