Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么赢了';t控制更新/刷新中间进程 我有一个Windows窗体(C.*.NET),它有一个状态标签,在事件处理程序的过程中间,我似乎无法更新它。我的代码看起来像这样 void Process_Completed(object sender, EventArgs e) { string t = "Process is finished!"; this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t }); } void Process_Started(object sender, EventArgs e) { string t = "Process has begun"; this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t }); } private delegate void StatusLabelUpdator(string text); private void updateStatusLabel(string text) { StatusLabel1.Text = text; statusStrip1.Invalidate(); statusStrip1.Refresh(); statusStrip1.Update(); }_C#_.net_Controls_Refresh - Fatal编程技术网

C# 为什么赢了';t控制更新/刷新中间进程 我有一个Windows窗体(C.*.NET),它有一个状态标签,在事件处理程序的过程中间,我似乎无法更新它。我的代码看起来像这样 void Process_Completed(object sender, EventArgs e) { string t = "Process is finished!"; this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t }); } void Process_Started(object sender, EventArgs e) { string t = "Process has begun"; this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t }); } private delegate void StatusLabelUpdator(string text); private void updateStatusLabel(string text) { StatusLabel1.Text = text; statusStrip1.Invalidate(); statusStrip1.Refresh(); statusStrip1.Update(); }

C# 为什么赢了';t控制更新/刷新中间进程 我有一个Windows窗体(C.*.NET),它有一个状态标签,在事件处理程序的过程中间,我似乎无法更新它。我的代码看起来像这样 void Process_Completed(object sender, EventArgs e) { string t = "Process is finished!"; this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t }); } void Process_Started(object sender, EventArgs e) { string t = "Process has begun"; this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t }); } private delegate void StatusLabelUpdator(string text); private void updateStatusLabel(string text) { StatusLabel1.Text = text; statusStrip1.Invalidate(); statusStrip1.Refresh(); statusStrip1.Update(); },c#,.net,controls,refresh,C#,.net,Controls,Refresh,当我运行代码时,一旦进程启动,就会触发process_start方法,几秒钟后就会触发process_Completed方法。由于某些原因,我无法使状态标签显示“进程已开始”。它只显示“流程已完成!”。如您所见,我尝试过使包含状态标签的状态条无效、刷新和更新,但没有成功。我无法对statuslabel本身调用update/refresh/invalidate,因为这些方法对它不可用。我做错了什么 新增信息: “流程”是通过单击表单上的按钮启动的,该表单在单独的类中调用一个方法,如下所示: pub

当我运行代码时,一旦进程启动,就会触发process_start方法,几秒钟后就会触发process_Completed方法。由于某些原因,我无法使状态标签显示“进程已开始”。它只显示“流程已完成!”。如您所见,我尝试过使包含状态标签的状态条无效、刷新和更新,但没有成功。我无法对statuslabel本身调用update/refresh/invalidate,因为这些方法对它不可用。我做错了什么

新增信息:

“流程”是通过单击表单上的按钮启动的,该表单在单独的类中调用一个方法,如下所示:

public void DoSomeProcess()
{
    TriggerProcessStarted();
    System.Threading.Thread.Sleep(2000);   // For testing..
    TriggerProcessComplete();
}
在TriggerProcessxxxx方法中,我使用以下代码触发事件

var EventListeners = EH.GetInvocationList();    //EH is the appropriate EventHandler
if (EventListeners != null)
{
    for (int index = 0; index < EventListeners.Count(); index++)
    {
        var methodToInvoke = (EventHandler)EventListeners[index];
        methodToInvoke.BeginInvoke(this, EventArgs.Empty, EndAsyncEvent, new object[] { });
    }
}
所以我猜“处理”是在UI线程上进行的,但eventhandler是在它自己的线程上调用的,然后在UI线程上调用控件更新。这是一种愚蠢的做事方式吗?注意:包含DoSomeProcess()方法的类位于我正在引用的单独的.NET类库中。

如果您在UI线程上执行处理,则在处理运行时,它将无法执行任何其他操作(如重新绘制更新的标签)。例如,如果处理是因为用户单击了一个按钮而被按钮单击处理程序触发的(没有显式地将其放在另一个线程上),那么它将在UI线程上运行。即使您更新了标签的文本,它也不会被绘制,直到它收到绘制消息,此时它可能正忙于处理

答案是在计算机上进行长时间运行的处理。黑客(IMHO)是用来让UI线程在处理过程中执行一些UI任务的。如果您在更新标签后,在开始处理之前,放置其中一个标签,则重新绘制标签的几率非常高。但是,在处理过程中,无法处理进一步的绘制事件(当有人将另一个应用程序窗口移到您的应用程序上并返回时,会导致半绘制窗口,等等)。因此我称之为黑客(尽管,呃,嗯,大家都知道我会这么做:-)

编辑根据您的编辑进行更新:

所以我猜“处理”是在UI线程上进行的,但eventhandler是在它自己的线程上调用的

我假设
DoSomeProcess
是从UI线程触发的(例如,直接响应按钮单击或类似操作)。如果是这样,那么是的,您的处理肯定在UI线程上。因为
TriggerProcessStarted
通过
BeginInvoke
异步触发回调,所以您不知道回调何时运行,但在任何情况下,您的代码都会立即启动处理,从不让步,因此其他人将无法抓住该线程。由于这是UI线程,对代理的调用将在设置标签文本的
Invoke
调用上阻塞,因此它必须等待UI线程(正在忙着处理)。(这是假设它被安排在一个不同的线程上;我无法100%说服自己,因为微软有两个不同的
BeginInvoke
s——IIRC的一位设计师承认这是一个非常愚蠢的想法——而且我已经有一段时间没有和这个东西斗争了。)


如果对回调进行
TriggerProcessStarted
调用,您应该不会有问题。但理想的情况是,在自己的线程上安排处理(如果它不执行UI)。

我尝试了你的“黑客”方法,但似乎没有任何帮助。我现在为上面的问题添加了更多细节。编辑后:你是对的。我离开了BeginInvoke,但改变了我的按钮点击事件,在它自己的线程上开始DoSomeWork。这就解决了!
private void updateStatusLabel(string text)
{
    StatusLabel1.Text = text;
    statusStrip1.Refresh();
    Application.DoEvents(); 
}