在运行进程时更新wpf UI

时间:2017-07-20 11:51:38

标签: c# wpf multithreading

我想要在单击按钮时显示自定义WPF控件,并在处理完成时隐藏,我正在尝试此操作,但在处理完成之前控件不可见。

public delegate void UpdateTextCallback(string message);

private void UpdateText(string message)
{
    if (message == "v")
        crclLoading.Visibility = Visibility.Visible;
    else
        crclLoading.Visibility = Visibility.Hidden;
}

private void TestThread()
{
    crclLoading.Dispatcher.Invoke(
        new UpdateTextCallback(this.UpdateText),
        new object[] {"v" }
    );
}

private void TestThread2()
{
    crclLoading.Dispatcher.Invoke(
        new UpdateTextCallback(this.UpdateText),
        new object[] { "s" }
    );
}

并在butoon_click:

Thread show= new Thread(new ThreadStart(TestThread));
show.Start();
//long time conusming processing
Thread hide= new Thread(new ThreadStart(TestThread2));
hide.Start();

2 个答案:

答案 0 :(得分:2)

您在后台线程上所做的就是调用Dispatcher.Invoke,这会在UI线程上同步执行指定的委托。

此外,您在启动第一个线程后立即启动第二个线程,而您的代码根本没有多大意义。

您需要在后台线程上实际执行一些可能长时间运行的操作。

顺便说一下,在后台线程上执行某些操作的推荐方法是现在启动一个新的Task。试试这个:

crclLoading.Visibility = Visibility.Visible;
Task.Factory.StartNew(()=> 
{
    //do something that might take a while here....
    System.Threading.Thread.Sleep(5000);
}).ContinueWith(task => 
{
//and then set the Visibility to Hidden once the task has finished
crclLoading.Visibility = Visibility.Hidden;
}, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());

答案 1 :(得分:2)

在WPF中,只有创建DispatcherObject的线程才能访问该对象。例如,从主UI线程分离出来的后台线程无法更新在UI线程上创建的Button的内容。为了让后台线程访问Button的Content属性,后台线程必须将工作委托给与UI线程关联的Dispatcher。这是通过使用InvokeBeginInvoke来完成的。 Invoke是同步的,BeginInvoke是异步的。该操作将添加到指定Dispatcher的{​​{1}}的事件队列中。 DispatcherPriority是同步操作;因此,在回调函数返回之前,控件不会返回调用对象。

使用Invoke