如何在BeginInvoke中使用Thread.Sleep

3
我尝试通过以下代码将 TextBox.Text 更新为 1 到 10,每秒内更新一次。但我不明白为什么整个界面会在更新成 10 前睡眠了 10 秒。我认为 Thread.Sleep(1000) 应该属于由 Dispatcher.BeginInvoke 创建的单独后台线程。请问我的代码有什么问题?
Thread t1 = new Thread(new ThreadStart(
    delegate()
    {
        this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
            new Action(delegate()
                {
                    for (int i = 1; i < 11; i++)
                    {
                        mytxt1.Text = "Counter is: " + i.ToString();
                        Thread.Sleep(1000);
                    }
                }));

    }));
t1.Start();

你很可能没有使用单独的后台线程。我非常确定这一点,因为如果你这样做了,你会收到一个错误,指出mytxt1是从不同的线程访问的,而不是在创建它的线程上。如何解决?请参考此教程:http://www.dreamincode.net/forums/topic/246911-c%23-multi-threading-in-a-gui-environment/ - 2pietjuh2
2个回答

6

您的代码仅创建新线程,以便强制调度程序将您的操作与UI线程同步。我猜您添加了Dispatcher.BeginInvoke是因为从另一个线程更改mytxt1.Text会导致异常。请尝试以下方法:

Thread t1 = new Thread(new ThreadStart(
    delegate()
    {
        for (int i = 1; i < 11; i++)
        {        
            var counter = i; //for clouser it is important
            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                new Action(delegate()
                {                    
                    mytxt1.Text = "Counter is: " + counter.ToString();                                         
                }));
           Thread.Sleep(1000);
        }
    }

2

设置文本的操作正在UI线程上运行,这就是为什么UI会冻结的原因。

由于只有创建UI控件实例的线程(也称为UI线程)才能修改UI控件的属性,因此您必须在UI线程上运行设置文本的代码。而这正是您正在做的事情。

您可以尝试在Threading.Timer中运行该代码。

或者...使用您已经拥有的代码,您应该像下面这样做,它可能会起作用:

Thread t1 = new Thread(new ThreadStart(
delegate()
{
    for (int i = 1; i < 11; i++)
    {
    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
        new Action(delegate()
            {                        
                    mytxt1.Text = "Counter is: " + i.ToString();                           

            }));
     Thread.Sleep(1000);
     }             
}));
t1.Start();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接