English 中文(简体)
您如何不断更新数据网(或任何其他数据控制系统),而不冻结数据系统?
原标题:How do you update a datagrid (or any other UI control) continuously without freezing the UI?

In a WinForms application, I have a datagrid that is associated to a datasource. As and when data comes in through a background thread the dataset needs to be updated which in turn automatically updates the datagrid. Now, the updates can be in the order of say, 7000 updates per 20 seconds. The probelm is that the UI hangs when such an update happens because it has to happen on the main thread. Is there a know solution for this problem?

一般来说,如果在未冻结申请的情况下不断更新《国际不动产合同》,你如何在温恩森林设计高绩效的企业申请?


Adding a scenario to explain this:

考虑这一设想。 你的树木观点是你用来代表某些等级数据。 现在,有关树木的最新数据是同yn。 服务器可以同时发布1或1 000份最新情况。 更新可以是修改现有项目或增加新节点。 需要指出的是,最新情况不能拖延。 这些节点代表着一个实时的实体。 发布最新情况后,将使用户认为会议本身被推迟。 因此,必须这样做。 如果可能的话(从业务逻辑观点来看),我会做很长的时间。

www.un.org/Depts/DGACM/index_spanish.htm 关键之处是: 所有数据不必同时显示。

因此,人们更想提出这一点:

www.un.org/Depts/DGACM/index_spanish.htm 添加一名背景工人,因为read子必须转向主线以进行更新。 工人的胎面不会改变。

最佳回答

处理服务器数据或实际将数据输入GridView方面的瓶颈吗? 如果是,虚拟模式可以帮助:

问题回答

www.un.org/Depts/DGACM/index_spanish.htm 不能,除非你想使用直接X。

视窗表格不是用于实时信息显示。 正如其他许多人指出的那样,你可以非常接近,但是由于“黎明”的方式。 视窗信息循环工程,you绝对不能保证,即使你创造了60赫兹标尺的时光。 即使你以事件驱动的方式这样做,但Windows仍将找WM_。 如果你在寻找实时展示,那势必会很晚。

如果你真的要展示出一种极好的东西,那么你就必须执行类似于<>Game Loop的东西。

For an explanation of why the Windows Message loop won t work for real-time display, and what a game loop is, see: http://www.mvps.org/directx/articles/writing_the_game_loop.htm

计算机游戏不可能出现任何可预见的拖延,因此,大多数计算机游戏都试图优化性能,以便在60赫兹圣杯或以上的圣杯上达到基准。 (只有24hz才会预测,你是否认为它们是“拖延的”?)

www.un.org/Depts/DGACM/index_spanish.htm 用实时显示书写申请是非曲线,我高度建议考虑以下列任何方式损害Windows提供的内容:

  • Create a timer that queues up screen updates at an acceptable rate (10 or more times per second). The user will not perceive the event as delayed, because a user cannot perceive delays that occur at a small fraction of a second.
  • Raise an event when the underlying data changes and let Windows to decide when to update the display (this will virtually always be acceptable).
  • If possible, come up with an alternate display that is not grid-based. Perhaps a scrolling console, or some other interface that displays the relevant information without overwriting old information. This may not be applicable, but coming up with another interface idea is often a good approach when the interface you want won t work.

If you really, really still want a very high-performance user interface, and write a game loop, you can do so in C# and paint a grid on your own to a DirectX surface. Once you get the hang of DirectX, drawing a grid is fairly easy, it s just a bunch of lines. With this approach you will avoid dealing with the Windows message loop, and potentially approach real-time performance.

Here s a great tutorial on how to use DirectX and how to render on a Windows form:

http://www.godpatterns.com/2005/02/using-directx-and-c-sharp-to-create.html

你在评论中说,你的繁重处理常常是报告进展情况,你可以不提任何报告(因为报告是需要显示的真实数据)。

你们应该做的是执行(双重)缓冲,向缓冲工作报告进展,并且每次与全球倡议同步进行缓冲。

Pseudocode如下:

DataGrid Grid; // This displays the data
List<object> DataBuffer; // Frequent updates are performed on this list

void BackgroundThreadLoop()
{
   while(true) // This loop iterates 7000 times in 20 seconds
   {
       var result = DoSomeHeavyCalculations();

       // Depending on the nature of the result, you can either just add it to list
       // or perhaps modify existing entries in the list in some way.
       DataBuffer.Add(result); // The simple case
       PerformSomeUpdating(DataBuffer, result); // The complicated case
   }
}

Timer RefreshTimer;
override void OnLoad()
{
    RefreshTimer = new Timer();
    RefreshTimer.Interval = 500; // easy to experiment with this
    RefreshTimer.Tick += (s, ea) => DrawBuffer(DataBuffer);
}

void DrawBuffer(List<object> DataBuffer)
{
    // This should copy DataBuffer and put it in the grid as fast as possible.

    // How to do this really depends on how the list changes and what it contains.
    // If it s just a list of strings:
    Grid.DataSource = DataBuffer.ToList(); // Shallow copy is OK with strings

    // If it s a list of some objects that have meaningful Clone method:
    Grid.DataSource = DataBuffer.Select(o => o.Clone).ToList();

    // If the number of elements is like constant and only some values change,
    // you could use some Dictionary instead of List and just copy values.
}

如果你提供更准确的信息,我或许能够进一步帮助。

UPDATE

有了新细节,我建议把个人带至物体changes。 代表某些物体结构变化的最一般方式是功能(或许是无参数的<代码> 行动)。 在接受修改的同时,你还修建了更新功能,直接修改了有观点的数据,并将这些数据储存在缓冲区:

List<Action> UpdateBuffer;
void OnUpdateReceived(MyType objToModify, object newValue)
{
    // The point is to make the lambda (below) as efficient as you can; 
    // finding the object and preparing the update should be done here, so that
    // no time is wasted during redraw in the main thread.

    UpdateBuffer.Add(() => objToModify.ApplyNewValueInSomeWay(newValue));


    // some other method should be constructed to add data to the view, but you get the point
}

现在,(名称不再充分,但无一例外)方法容易:

void DrawBuffer()
{
    List<Action> bufferCopy;
    lock(UpdateBuffer) // the other thread should also lock the buffer for adding
    {
        bufferCopy = UpdateBuffer.ToList();
        UpdateBuffer.Clear();
    }
    view.SuspendLayout();
    foreach(Action a in bufferCopy)
        a();
    view.ResumeLayout();
}

显然,我没有尝试这一准确的解决办法,但它使你有能力控制重排频率和重整批集,而不是单一更新。

我刚刚做了抽样申请,将通过背景工作者填写内部名单,数据将在数据GridView中显示。 如果符合你的要求,你可以改变发现的字句速度:

最为令人感兴趣的部分应当是守则本身的形式:

public partial class FormMain : Form
{
    private List<Person> _Persons;
    private Random _Random;
    private int _TimeoutBetweenInserts;

    public FormMain()
    {
        InitializeComponent();

        // Initialize our private fields
        _Random = new Random();
        _Persons = new List<Person>();
        _TimeoutBetweenInserts = (int)numericUpDownTimeoutBetweenInserts.Value;

        // Attach the list to the binding source and get informed on list changes.
        personBindingSource.DataSource = _Persons;
        personBindingSource.ListChanged += (sender, e) => labelDataGridViewCount.Text = _Persons.Count.ToString();
    }

    private void OnBackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
    {
        var spinner = new SpinWait();
        var worker = (BackgroundWorker)sender;

        // Should we abort our adding?
        while (!worker.CancellationPending)
        {
            // Create a new entry ...
            var person = new Person();

            person.Index = _Persons.Count;
            person.Born = new DateTime(_Random.Next(1950, 2012), _Random.Next(1, 13), _Random.Next(1, 28));
            person.FirstName = "Hello";
            person.LastName = "World";

            // ... and add it to the list
            _Persons.Add(person);

            // Do a little waiting ... (to avoid blowing out the list)
            for (int i = 0; i < _TimeoutBetweenInserts; i++)
            {
                spinner.SpinOnce();
            }

            spinner.Reset();
        }

    }

    private void OnBackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // Stop the gui updater, cause the background worker also stopped.
        timerGuiUpdater.Stop();
    }

    private void OnCheckBoxToggleWorkerCheckedChanged(object sender, EventArgs e)
    {
        // Update the "button" according to the state
        checkBoxToggleWorker.Text = checkBoxToggleWorker.Checked ? "&Pause" : "&Start";

        if (checkBoxToggleWorker.Checked)
        {
            if (!backgroundWorker.IsBusy)
            {
                // Start the gui updater and the background worker
                timerGuiUpdater.Start();
                backgroundWorker.RunWorkerAsync();
            }
        }
        else
        {
            // Stop the background worker
            backgroundWorker.CancelAsync();
        }
    }

    private void OnNumericUpDownTimeoutBetweenInsertsValueChanged(object sender, EventArgs e)
    {
        // Update the internal value, to let it propagate into the background worker
        _TimeoutBetweenInserts = (int)numericUpDownTimeoutBetweenInserts.Value;
    }

    private void OnTimerGuiUpdaterTick(object sender, EventArgs e)
    {
        // Tell the BindingSource it should inform its clients (the DataGridView)
        // to update itself
        personBindingSource.ResetBindings(false);
    }
}

让你在形式上进入所有这些领域,这里是设计者。

partial class FormMain
{
    /// <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.dataGridView = new System.Windows.Forms.DataGridView();
        this.Index = new System.Windows.Forms.DataGridViewTextBoxColumn();
        this.lastNameDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
        this.firstNameDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
        this.bornDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
        this.ageDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
        this.personBindingSource = new System.Windows.Forms.BindingSource(this.components);
        this.backgroundWorker = new System.ComponentModel.BackgroundWorker();
        this.labelDataGridViewCountText = new System.Windows.Forms.Label();
        this.labelDataGridViewCount = new System.Windows.Forms.Label();
        this.labelSpinsBetweenInsertsText = new System.Windows.Forms.Label();
        this.numericUpDownTimeoutBetweenInserts = new System.Windows.Forms.NumericUpDown();
        this.checkBoxToggleWorker = new System.Windows.Forms.CheckBox();
        this.timerGuiUpdater = new System.Windows.Forms.Timer(this.components);
        ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit();
        ((System.ComponentModel.ISupportInitialize)(this.personBindingSource)).BeginInit();
        ((System.ComponentModel.ISupportInitialize)(this.numericUpDownTimeoutBetweenInserts)).BeginInit();
        this.SuspendLayout();
        // 
        // dataGridView
        // 
        this.dataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
        | System.Windows.Forms.AnchorStyles.Left) 
        | System.Windows.Forms.AnchorStyles.Right)));
        this.dataGridView.AutoGenerateColumns = false;
        this.dataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
        this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
        this.dataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
        this.Index,
        this.lastNameDataGridViewTextBoxColumn,
        this.firstNameDataGridViewTextBoxColumn,
        this.bornDataGridViewTextBoxColumn,
        this.ageDataGridViewTextBoxColumn});
        this.dataGridView.DataSource = this.personBindingSource;
        this.dataGridView.Location = new System.Drawing.Point(12, 12);
        this.dataGridView.Name = "dataGridView";
        this.dataGridView.Size = new System.Drawing.Size(560, 212);
        this.dataGridView.TabIndex = 0;
        // 
        // Index
        // 
        this.Index.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
        this.Index.DataPropertyName = "Index";
        this.Index.HeaderText = "Index";
        this.Index.Name = "Index";
        this.Index.Width = 58;
        // 
        // lastNameDataGridViewTextBoxColumn
        // 
        this.lastNameDataGridViewTextBoxColumn.DataPropertyName = "LastName";
        this.lastNameDataGridViewTextBoxColumn.HeaderText = "LastName";
        this.lastNameDataGridViewTextBoxColumn.Name = "lastNameDataGridViewTextBoxColumn";
        // 
        // firstNameDataGridViewTextBoxColumn
        // 
        this.firstNameDataGridViewTextBoxColumn.DataPropertyName = "FirstName";
        this.firstNameDataGridViewTextBoxColumn.HeaderText = "FirstName";
        this.firstNameDataGridViewTextBoxColumn.Name = "firstNameDataGridViewTextBoxColumn";
        // 
        // bornDataGridViewTextBoxColumn
        // 
        this.bornDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
        this.bornDataGridViewTextBoxColumn.DataPropertyName = "Born";
        this.bornDataGridViewTextBoxColumn.HeaderText = "Born";
        this.bornDataGridViewTextBoxColumn.Name = "bornDataGridViewTextBoxColumn";
        this.bornDataGridViewTextBoxColumn.Width = 54;
        // 
        // ageDataGridViewTextBoxColumn
        // 
        this.ageDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
        this.ageDataGridViewTextBoxColumn.DataPropertyName = "Age";
        this.ageDataGridViewTextBoxColumn.HeaderText = "Age";
        this.ageDataGridViewTextBoxColumn.Name = "ageDataGridViewTextBoxColumn";
        this.ageDataGridViewTextBoxColumn.ReadOnly = true;
        this.ageDataGridViewTextBoxColumn.Width = 51;
        // 
        // personBindingSource
        // 
        this.personBindingSource.DataSource = typeof(WindowsFormsApplication.Person);
        // 
        // backgroundWorker
        // 
        this.backgroundWorker.WorkerSupportsCancellation = true;
        this.backgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.OnBackgroundWorkerDoWork);
        this.backgroundWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.OnBackgroundWorkerRunWorkerCompleted);
        // 
        // labelDataGridViewCountText
        // 
        this.labelDataGridViewCountText.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
        this.labelDataGridViewCountText.Location = new System.Drawing.Point(12, 230);
        this.labelDataGridViewCountText.Name = "labelDataGridViewCountText";
        this.labelDataGridViewCountText.Size = new System.Drawing.Size(50, 23);
        this.labelDataGridViewCountText.TabIndex = 1;
        this.labelDataGridViewCountText.Text = "Count:";
        this.labelDataGridViewCountText.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
        // 
        // labelDataGridViewCount
        // 
        this.labelDataGridViewCount.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
        this.labelDataGridViewCount.Location = new System.Drawing.Point(68, 230);
        this.labelDataGridViewCount.Name = "labelDataGridViewCount";
        this.labelDataGridViewCount.Size = new System.Drawing.Size(82, 23);
        this.labelDataGridViewCount.TabIndex = 2;
        this.labelDataGridViewCount.Text = "0";
        this.labelDataGridViewCount.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
        // 
        // labelSpinsBetweenInsertsText
        // 
        this.labelSpinsBetweenInsertsText.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
        this.labelSpinsBetweenInsertsText.Location = new System.Drawing.Point(265, 230);
        this.labelSpinsBetweenInsertsText.Name = "labelSpinsBetweenInsertsText";
        this.labelSpinsBetweenInsertsText.Size = new System.Drawing.Size(155, 23);
        this.labelSpinsBetweenInsertsText.TabIndex = 3;
        this.labelSpinsBetweenInsertsText.Text = "Spins between inserts:";
        this.labelSpinsBetweenInsertsText.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
        // 
        // numericUpDownTimeoutBetweenInserts
        // 
        this.numericUpDownTimeoutBetweenInserts.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
        this.numericUpDownTimeoutBetweenInserts.Increment = new decimal(new int[] {
        10,
        0,
        0,
        0});
        this.numericUpDownTimeoutBetweenInserts.Location = new System.Drawing.Point(426, 233);
        this.numericUpDownTimeoutBetweenInserts.Maximum = new decimal(new int[] {
        500,
        0,
        0,
        0});
        this.numericUpDownTimeoutBetweenInserts.Minimum = new decimal(new int[] {
        10,
        0,
        0,
        0});
        this.numericUpDownTimeoutBetweenInserts.Name = "numericUpDownTimeoutBetweenInserts";
        this.numericUpDownTimeoutBetweenInserts.Size = new System.Drawing.Size(65, 20);
        this.numericUpDownTimeoutBetweenInserts.TabIndex = 4;
        this.numericUpDownTimeoutBetweenInserts.ThousandsSeparator = true;
        this.numericUpDownTimeoutBetweenInserts.Value = new decimal(new int[] {
        500,
        0,
        0,
        0});
        this.numericUpDownTimeoutBetweenInserts.ValueChanged += new System.EventHandler(this.OnNumericUpDownTimeoutBetweenInsertsValueChanged);
        // 
        // checkBoxToggleWorker
        // 
        this.checkBoxToggleWorker.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
        this.checkBoxToggleWorker.Appearance = System.Windows.Forms.Appearance.Button;
        this.checkBoxToggleWorker.Location = new System.Drawing.Point(497, 230);
        this.checkBoxToggleWorker.Name = "checkBoxToggleWorker";
        this.checkBoxToggleWorker.Size = new System.Drawing.Size(75, 23);
        this.checkBoxToggleWorker.TabIndex = 6;
        this.checkBoxToggleWorker.Text = "&Start";
        this.checkBoxToggleWorker.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
        this.checkBoxToggleWorker.UseVisualStyleBackColor = true;
        this.checkBoxToggleWorker.CheckedChanged += new System.EventHandler(this.OnCheckBoxToggleWorkerCheckedChanged);
        // 
        // timerGuiUpdater
        // 
        this.timerGuiUpdater.Tick += new System.EventHandler(this.OnTimerGuiUpdaterTick);
        // 
        // FormMain
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(584, 262);
        this.Controls.Add(this.checkBoxToggleWorker);
        this.Controls.Add(this.numericUpDownTimeoutBetweenInserts);
        this.Controls.Add(this.labelSpinsBetweenInsertsText);
        this.Controls.Add(this.labelDataGridViewCount);
        this.Controls.Add(this.labelDataGridViewCountText);
        this.Controls.Add(this.dataGridView);
        this.MinimumSize = new System.Drawing.Size(600, 300);
        this.Name = "FormMain";
        this.Text = "DataGridView Performance Tester";
        ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit();
        ((System.ComponentModel.ISupportInitialize)(this.personBindingSource)).EndInit();
        ((System.ComponentModel.ISupportInitialize)(this.numericUpDownTimeoutBetweenInserts)).EndInit();
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.DataGridView dataGridView;
    private System.ComponentModel.BackgroundWorker backgroundWorker;
    private System.Windows.Forms.BindingSource personBindingSource;
    private System.Windows.Forms.Label labelDataGridViewCountText;
    private System.Windows.Forms.Label labelDataGridViewCount;
    private System.Windows.Forms.Label labelSpinsBetweenInsertsText;
    private System.Windows.Forms.NumericUpDown numericUpDownTimeoutBetweenInserts;
    private System.Windows.Forms.CheckBox checkBoxToggleWorker;
    private System.Windows.Forms.Timer timerGuiUpdater;
    private System.Windows.Forms.DataGridViewTextBoxColumn Index;
    private System.Windows.Forms.DataGridViewTextBoxColumn lastNameDataGridViewTextBoxColumn;
    private System.Windows.Forms.DataGridViewTextBoxColumn firstNameDataGridViewTextBoxColumn;
    private System.Windows.Forms.DataGridViewTextBoxColumn bornDataGridViewTextBoxColumn;
    private System.Windows.Forms.DataGridViewTextBoxColumn ageDataGridViewTextBoxColumn;
}

最后但并非最不重要的是,我用于有效载荷的几类人员:

public class Person
{
    public int Age
    {
        get
        {
            // ToDo: better algorithm to determine real age is left as an exercise to the reader. ;-)
            var age = (int)((DateTime.Now - Born).TotalDays / 365);
            return Math.Max(0, age);
        }
    }

    public DateTime Born { get; set; }

    public string FirstName { get; set; }

    public int Index { get; set; }

    public string LastName { get; set; }
}

您是否利用了一名背景工作者? 规定在多工作活动中要求冻结的法规:

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
 {
     YourFreezingCodeHere
 }

开始背景 工人

backgroundWorker1.RunWorkerAsync();

制图股将始终通过主线/全线更新。 这是温森林发挥作用的方式。

你们可以做的是,防止“国际倡议”过于接近。 为此:

  1. Make sure you execute all other processing on one or more different threads.
  2. Only update the UI when useful for the user. I can t see/read a number that is changing every 3 ms so skip DISPLAYING the update.

请注意,我使用“观点、观点和模式”是本答复的其余部分。 我不是强迫你使用地雷影响控制器,而是使解释情况更加容易。 你们也可以以同样的方式使用MVP或MVC。

您可以创立一种特殊类型的观点,在X毫米秒后引发一场事件,以检查ir脏的借方,并引起适当的不动产交易。 这将要求你在财产制板上设定ir权,而NOT则在造物人中提出 Property权。

或许更可取的是,在上次更新观点时,更能跟踪情况;如果比x毫秒前更长,则从《模式》中更新观点。 这保证了金融情报局与《观点》的合议。 但是,你们必须认识到,《观点》与《模式》并不相同。 当然,可以制定方法,明确归纳模型。

这两者之间的选择可能取决于你们如何考虑观点和观点之间的关系,以及计算成本的时间。

Application.DoEvents();

在车内使用这种方法。

private void timer1_Tick(object sender, EventArgs e)
{
     Application.DoEvents();
}

你们应当开始时间,以便冻结或让你开始实行。 间隔时间为时数,为时数确定次数。 例例为10例。

timer1.Start();
timer1.Interval = 10;

我已经做了大量大量数据转移(每秒重),如此,我认为数据分析只是你想要的控制。 该系统旨在提供数据并使用户对数据进行编辑,但并未真正优化数据作为信息流。 在这一卷中,它赢得的用户对实时观察数据非常好,只是一个数据流太大,而且很快就能够感受到。

我建议你继续使用背景工作者从事这项工作(如你说过的那样),并利用报告进展方法将一定比例的成绩带回进步。 你还可以在网页上更新一个贴有你重新工作的标签。 标签将自动更新,而不是冻结贵单位。 为了做到这一点,在背景工作者的召唤中形成了一个实例变量。 在您的工会组织上,树立了这一类的榜样,在背景中,工人的进步方法将贵工会的标签贴在你的班级变量上。 每次请背景工作人员时,都会更新。 报告编制

然后把所有胎儿放在一个记录中,这样,人们就可以在稍后看到。 在350项修改/秒中尝试视而不见。

re: The problem is that the UI hangs when such an update happens because it has to happen on the main thread. Is there a known solution for this problem?

页: 1

一般而言,如果在申请没有冻结的情况下不断更新《国际不动产合同》,你如何设计在温Forms的高绩效企业申请?

在你重新描述的比额表中,你可以 t。 限制贵组织控制的范围,这样它就不试图一劳永逸地展示任何地方发生的一切,而是迫使用户选择一个能够以可接受的速度更新的地区。

我建议使用两层处理这一设想。

非倡议 数据层:

这个层能够从你的背景线上 all取所有最新数据,并生成最后数据标(Let称其目标X),这是最新和最新数据。 这一层应自成一体,根本不会影响“情报”。 另外,在接到任何更新后,你还可以有一个蓝色变数(Let称其为“新最新情况”),并将它确定为事实,表明已经收到了新的变化。 Don tabes利用Thread-safe locking机制,将这种变数确定为现实,以避免出现一致的问题。

• 共同市场:

这个层次也可以在离散的路上运行。 如果自上次国际调查更新以来有任何新的数据,通过核对新的最新数据变量,如果存在,那么你就可以有一个时间来检查具体的间隔(*),然后确定新的最新数据,以伪造和生成新的数据子集(***)。 Don tabes在生成数据分集和更新最新外观变量时使用lock锁。

After generating your sub-set of data then you need to Invoke another method by control (In UI Thread) to apply this sub-set of data to the control. This is where UI thread will block until process done so you need to make this method as light as possible! All heavy stuff needs to be done outside of Invoke and only part that relate to UI control needs to be in that method.

(*) As "Hans Passant" mentioned in his comment, human eye only can process 50 milliseconds refresh, but I even suggest to increase this to 100 msec. You can get some ideas from this thread: What is the shortest perceivable application response delay?

(**) 本案的部分内容是,如何更新你的控制,只提供所需的数据,而不是把所有数据一劳永逸地推给国际交易日志。 我确实建议实行海关控制,以处理这一问题,而不是使用标准控制;因为你能够充分接触到如何和何时更新国际调查,并且能够取得最佳业绩。 例如,关于Gred,你可以发现第一个可见的项目和可以展示于德国马克的物品数量,只是更新这一部分,而不是试图用所有数据更新控制。

Sorry, I know I suppose to explain solution in short message but this is the shortest version that I can came across. I hope this helps :-)

http://msdn.microsoft.com/en-us/library/ms996483.aspx” rel=“nofollow”>MSDN 。 我希望这一帮助。

Use backgroundWorker, it will run inserted code in separated thread, so the application will not freeze.

 public void backgroundWorkerPinger_DoWork(object sender, DoWorkEventArgs e)
        {

            Ping ping = new Ping();

                try
                {
                    PingReply pingreply = ping.Send("46.4.106.10", 500);
                    string active = pingreply.Status.ToString();
                    if (active == "Success")
                    {
                        //Pokud je spojení aktivni pak se nastavi barva labelu na zelenou a vypise se aktivni
                        ActiveOrNotLabel.ForeColor = Color.Green;
                        ActiveOrNotLabel.Text = "Aktivní";
                       // MessageBox.Show("vyjimka2");
                        if (connection_enabled == false)
                        {
                            admini.Enabled = true;
                            connection_enabled = true;
                        }
                    }
                    if (active != "Success") {
                        ActiveOrNotLabel.ForeColor = Color.Red;
                        ActiveOrNotLabel.Text = "Neaktivní";
                        admini.Enabled = false;
                        connection_enabled = false;

                     }
                }
                catch
                {
                    //Jinak na cervenou a neaktivni

                    //MessageBox.Show("vyjimka");
                    ActiveOrNotLabel.ForeColor = Color.Red;
                    ActiveOrNotLabel.Text = "Neaktivní";
                    admini.Enabled = false;
                    connection_enabled = false;

                }
            }




相关问题
Bring window to foreground after Mutex fails

I was wondering if someone can tell me what would be the best way to bring my application to the foreground if a mutex was not able to be created for a new instance. E.g.: Application X is running ...

How to start WinForm app minimized to tray?

I ve successfully created an app that minimizes to the tray using a NotifyIcon. When the form is manually closed it is successfully hidden from the desktop, taskbar, and alt-tab. The problem occurs ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

Handle DataTable.DataRow cell change event

I have a DataTable that has several DataColumns and DataRow. Now i would like to handle an event when cell of this DataRow is changed. How to do this in c#?

Apparent Memory Leak in DataGridView

How do you force a DataGridView to release its reference to a bound DataSet? We have a rather large dataset being displayed in a DataGridView and noticed that resources were not being freed after the ...

ALT Key Shortcuts Hidden

I am using VS2008 and creating forms. By default, the underscore of the character in a textbox when using an ampersand is not shown when I run the application. ex. "&Goto Here" is not ...

WPF-XAML window in Winforms Application

I have a Winforms application coded in VS C# 2008 and want to insert a WPF window into the window pane of Winforms application. Could you explain me how this is done.