C# 调用与表单加载并行更新标签并允许表单继续加载的函数

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

我将在表单加载期间调用几个函数,然后使用结果更新label控件。如果函数长时间运行,它将停止窗体加载。。。所以我想让窗体在两个函数并行调用时加载一个函数,当它们返回时,更新标签,这里是调用代码,两个函数都返回一个int

这是.Net 4.0中的windows窗体应用程序

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;

    }
}