Reputation: 9121
I have a custom WPF control that I want to show when a button is clicked and hide when processing is finished, I am trying this but the control is not visible until the processing is done.
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" }
);
}
and in butoon_click:
Thread show= new Thread(new ThreadStart(TestThread));
show.Start();
//long time conusming processing
Thread hide= new Thread(new ThreadStart(TestThread2));
hide.Start();
Upvotes: 1
Views: 4104
Reputation: 90
In WPF, only the thread that created a DispatcherObject
may access that object. For example, a background thread that is spun off from the main UI thread cannot update the contents of a Button
that was created on the UI thread. In order for the background thread to access the Content
property of the Button, the background thread must delegate the work to the Dispatcher associated with the UI thread. This is accomplished by using either Invoke
or BeginInvoke
. Invoke
is synchronous and BeginInvoke
is asynchronous. The operation is added to the event queue of the Dispatcher
at the specified DispatcherPriority
.
Invoke
is a synchronous operation; therefore, control will not return to the calling object until after the callback returns.
use Dispatcher.Invoke(new Action(() => MethodName));
Upvotes: 2
Reputation: 169390
All you do on your background threads is to call Dispatcher.Invoke
and this executes the specified delegate synchronously on the UI thread.
Also, you start second thread right after you have started the first one and your code doesn't make much sense at all.
You need to actually perform some potentially long-running operation on the background thread.
By the way, the recommended way to execute something on a background thread is to start a new Task
nowadays. Try this:
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());
Upvotes: 2