如何使表单延迟显示

时间:2015-10-04 16:01:53

标签: c# winforms stopwatch timedelay

编辑:Application.DoEvents();这样做了。在这里找到:Force GUI update from UI Thread

c#,winforms。我希望以1为步长增加一个数字,并在列表视图中显示这些增量,以便用户看到数字向上计数(例如从10到15)。

我有另一个按钮,单击时增加1,并使用相同的显示()。它工作正常,并按预期更新显示。

我尝试了这些代码(缩短以节省空间):

(1)

for (int i = 0; i < 5; i++) 
{
    var t = Task.Run (async () =>
    {
        myInt++;
        await Task.Delay(300);
        display(); //forces screen refresh
    });
}

(2)

for (int i = 0; i < 5; i++) 
{
    var t = Task.Run (() =>
    {
        myInt++;
        Task.Delay(300).Wait;
        display();
    });
    //t.Wait(); //causes "An unhandled exception of type 'System.AggregateException' occurred in mscorlib.dll"
}

(3)

for (int i = 0; i < 5; i++) 
{
    myInt++;
    display();
    System.Threading.Thread.Sleep(300);
}

(4)

Stopwatch stopwatch = new Stopwatch();
for (int i = 0; i < 5; i++) 
{
    stopwatch.Restart();
    while (true)
    {
        if (stopwatch.ElapsedMilliseconds >= 300)
        {
            break;
        }
    }
stopwatch.Stop();
myInt++;
display();
}

都使用这个:

private void display()
{   
    myListView.Items.Clear();
    myListView.Items.Add(new ListViewItem(new[] { myInt }));
}

(1)和(2)将数字增加5,但显示不会更新。它显示何时通过其他功能更新显示。

(3)和(4)将数字增加5,但显示仅在约1500ms后更新,显示屏跳过单步并显示最终结果(例如15)。

任何使这项工作的建议?我可以以某种方式强制刷新display()函数吗?

为什么t.Wait();引起异常? (我在网上的某个地方找到了任务代码)

编辑:

(5)

private void team_comm_btn_all_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 5; i++) 
    {
            await Run(i); //error 74 see below
    }
}

private async Task Run(int i)
{
    myInt++;
    display();
    await Task.Delay(300);
}

await Run(i);给出以下内容: 错误74'await'运算符只能在异步方法中使用。考虑使用'async'修饰符标记此方法并将其返回类型更改为'Task'。

只是做“Run(i)”而是发出警告“等待”丢失......在这种情况下,它会毫不拖延地编译并递增5。

(6)

private void team_comm_btn_all_Click(object sender, EventArgs e)
{
   for (int i = 0; i < 5; i++) 
   {
       var task = Task.Run(async () =>
        {
            await Run(i);
        });
   }
}

private async Task Run(int i)
{
    myInt++;
    display();
    await Task.Delay(300);
}

增加5但根本不更新显示。

1 个答案:

答案 0 :(得分:0)

通常你会使用System.Windows.Forms.Timer。但async/await只要你理解它就会使这些事情变得微不足道(并仔细阅读编译器警告和错误信息)。不久,(5)是解决编译器错误的小修改的方法 但是从一开始就开始吧。假设您首先编写这样的正常同步版本(基本上是您的(3))

private void team_comm_btn_all_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 5; i++) 
    {
        if (i != 0) System.Threading.Thread.Sleep(300);
        myInt++;
        display();
    }
}

只是为了看到UI没有更新。因此,您决定将其变为异步,在async/await的帮助下,将Thread.Sleep替换为Task.Delay就像这样简单

private void team_comm_btn_all_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 5; i++) 
    {
        if (i != 0) await Task.Delay(300);
        myInt++;
        display();
    }
}

但现在无法使用以下错误进行编译

  

错误74'await'运算符只能在异步方法中使用。考虑使用'async'修饰符标记此方法并将其返回类型更改为'Task'。

信息很清楚。您必须使用async关键字标记您的方法。将返回类型更改为Task的其他建议怎么样呢,通常你应该考虑它,但由于你在事件处理程序内部,即一个无法更改签名的方法,你可以忽略那部分 - 那是允许async void的确切情况。

总而言之,您的最终代码将如下所示

private async void team_comm_btn_all_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 5; i++) 
    {
        if (i != 0) await Task.Delay(300);
        myInt++;
        display();
    }
}