C# 调用与表单加载并行更新标签并允许表单继续加载的函数
我将在表单加载期间调用几个函数,然后使用结果更新label控件。如果函数长时间运行,它将停止窗体加载。。。所以我想让窗体在两个函数并行调用时加载一个函数,当它们返回时,更新标签,这里是调用代码,两个函数都返回一个int 这是.Net 4.0中的windows窗体应用程序C# 调用与表单加载并行更新标签并允许表单继续加载的函数,c#,.net-4.0,C#,.net 4.0,我将在表单加载期间调用几个函数,然后使用结果更新label控件。如果函数长时间运行,它将停止窗体加载。。。所以我想让窗体在两个函数并行调用时加载一个函数,当它们返回时,更新标签,这里是调用代码,两个函数都返回一个int 这是.Net 4.0中的windows窗体应用程序 private void mainForm_Load(object sender, EventArgs e) { currentCount = func1(tes1); allowedCoun
private void mainForm_Load(object sender, EventArgs e)
{
currentCount = func1(tes1);
allowedCount= func2(test2);
labelCount.Text = "Using " + func1.ToString() + " of " + func2.ToString();
}
试着这样做:
new Thread(() => { /* make stuff and finally*/ formObject.Invoke });
有关从WinwdowsForms中的非UI线程更新UI的更详细示例,请访问Microsoft的页面或在中找到。请尝试以下操作:
new Thread(() => { /* make stuff and finally*/ formObject.Invoke });
有关从WinwdowsForms中的非UI线程更新UI的更详细示例,请参见Microsoft的页面,该页面位于或中。您需要的一切就是创建新线程并启动它
private void mainForm_Load(object sender, EventArgs e)
{
var thread = new Thread(() =>
{
currentCount = func1(tes1);
allowedCount= func2(test2);
labelCount.Text = "Using " + func1.ToString() + " of " + func2.ToString();
});
thread.Start();
}
在我看来,这就是你在winforms中需要做的一切。
我错了-您需要调用invoke函数。您所需要的一切就是创建新线程并启动它
private void mainForm_Load(object sender, EventArgs e)
{
var thread = new Thread(() =>
{
currentCount = func1(tes1);
allowedCount= func2(test2);
labelCount.Text = "Using " + func1.ToString() + " of " + func2.ToString();
});
thread.Start();
}
在我看来,这就是你在winforms中需要做的一切。
我错了-您需要调用invoke函数。EDIT
更具内聚性的变体,在func1和func2完成之前不会更新标签:
private void UpdateCountInBackground()
{
Task.Factory.StartNew(
() =>
{
int current = 0, allowed = 0;
Task.WaitAll(
Task.Factory.StartNew(() => current = func1()),
Task.Factory.StartNew(() => allowed = func2()));
Invoke(new Action(() =>
labelCount.Text = "Using " + current.ToString() + " of " + allowed.ToString()));
});
}
原创
你可以用它来做类似的事情
这将并行执行两个长时间运行的方法,当每个方法完成时,它将安全地更新标签线程。EDIT
更具内聚性的变体,在func1和func2完成之前不会更新标签:
private void UpdateCountInBackground()
{
Task.Factory.StartNew(
() =>
{
int current = 0, allowed = 0;
Task.WaitAll(
Task.Factory.StartNew(() => current = func1()),
Task.Factory.StartNew(() => allowed = func2()));
Invoke(new Action(() =>
labelCount.Text = "Using " + current.ToString() + " of " + allowed.ToString()));
});
}
原创
你可以用它来做类似的事情
这将并行执行两个长时间运行的方法,当每个方法完成时,它将安全地更新标签线程。更新2001-08-27以添加连续更新
我更新了代码,还展示了如何使用.Forms GUI计时器组件在后台更新时更新状态栏标签,以及一些不同的清理和附加注释。当然也可以使用Invoke()来更新表单中的信息,但我认为这样做没有多大意义。UI更新的目标是向用户提供足够的视觉反馈,并且不需要将字段的更新与视觉元素的更新耦合起来
此外,如果这些更新足够频繁,那么所有要调用的调用都可能会对性能造成很大影响,除非您对它们进行速率限制,这基本上就是计时器组件所发生的情况
我已压缩解决方案,并可供下载:。我不完全确定为什么我选择了那个名字,但你说得对
因此,代码现在演示了如何做到这两个方面:我最初解释的问题的意思是(在后台并行运行两个线程,在两个函数返回后更新标签),以及在后台线程中添加单独计数器字段的定期更新,这些线程的状态也显示在GUI上,由定时器
组件在其勾选
事件中更新标签实现
对于线程结束时的最终更新,此设置不需要超出结构已提供的任何同步,至少从更新内容的角度来看是这样的;我不知道你的实际功能是什么。(如果它们彼此交互,可能会有一些同步要求。)它还可以非常快速地更新表单,而不必担心两个线程之间的任何协调或同步,以确定哪个线程负责更新GUI
表格代码
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
使用系统诊断;
使用系统线程;
名称空间按钮\u 7208779
{
公共部分类名称:表单
{
公共财政收入()
{
初始化组件();
tslblRunStatus.Text=“正在更新:请稍候…”;
tslblFinalStatus.Text=“”;
线程背景线程=
新线程(()=>TwoParallelCalls_UpdateOnlyOnReturn());
BackgroundThread.Start();
//tmrUpdateStatus是一个计时器组件,放置在
//窗体处于设计模式。其初始设置为默认值
//Interval=100,Enabled=false,它的勾号事件
//已连接到tmrUpdateStatus_tick
tmrUpdateStatus.Start();
}
//组件计时器的优点是我们没有
//我们必须担心调用,我们已经知道
//勾号事件正在UI线程上发生。
私有void tmrUpdateStatus_勾选(对象发送方,事件参数e)
{
//如果在两个功能完成后触发勾号
如果((currentCount==-1)| |(allowedCount!=1))
{
tslblRunStatus.Text=
字符串格式(
“[正在运行…]使用{1}中的{0}”,
runCurrentCount,runAllowedCount
);
}
其他的
{
//我们可以使用它来停止计时器,因为我们正在执行
//在这里登记。如果我们不需要防止额外的
//函数完成后更新,我们可以跳过
//在这里办理登机手续,并在其他地方停止办理登机手续。(见下文)
tmrUpdateStatus.Stop();
}
}
//有一个通用的方法可以同时激发
//函数,然后等待两者都是没有特殊线程的
//同步器
namespace ParallelButtons_7208779
{
partial class frmMain
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.tslblRunStatus = new System.Windows.Forms.ToolStripStatusLabel();
this.tslblFinalStatus = new System.Windows.Forms.ToolStripStatusLabel();
this.tmrUpdateStatus = new System.Windows.Forms.Timer(this.components);
this.statusStrip1.SuspendLayout();
this.SuspendLayout();
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.tslblRunStatus,
this.tslblFinalStatus});
this.statusStrip1.Location = new System.Drawing.Point(0, 208);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(431, 22);
this.statusStrip1.TabIndex = 0;
this.statusStrip1.Text = "statusStrip1";
//
// tslblRunStatus
//
this.tslblRunStatus.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner;
this.tslblRunStatus.Name = "tslblRunStatus";
this.tslblRunStatus.Size = new System.Drawing.Size(80, 17);
this.tslblRunStatus.Text = "Item {0} of {1}";
//
// tslblFinalStatus
//
this.tslblFinalStatus.Name = "tslblFinalStatus";
this.tslblFinalStatus.Size = new System.Drawing.Size(60, 17);
this.tslblFinalStatus.Text = "final status";
//
// tmrUpdateStatus
//
this.tmrUpdateStatus.Tick += new System.EventHandler(this.tmrUpdateStatus_Tick);
//
// frmMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(431, 230);
this.Controls.Add(this.statusStrip1);
this.Name = "frmMain";
this.Text = "Background Form Updates - Stack Overflow 7208779";
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripStatusLabel tslblRunStatus;
private System.Windows.Forms.ToolStripStatusLabel tslblFinalStatus;
private System.Windows.Forms.Timer tmrUpdateStatus;
}
}