What I want to do: I'm using a web service DLL in WPF(c#). The DLL contains a web service that you can see it in my code as SmsSender class. Calling each method of this class is time-consuming so I need run its methods in other threads.

What I do: I set DataView object (that is "returned value" from method) to ItemsSource of DataGrid. So I use Dispatcher.BeginInvoke().

My problem: my problem is using Dispatcher.BeginInvoke() can freeze my program even I run it in a different thread. I want to call method without freezing. Is it possible to define a time-out?

Update1:

How can I set DataView from time-consuming method to DataGrid?

My code:

Action action = () =>
{
    SmsSender sms = new SmsSender();

    dgUser1.ItemsSource = sms.GetAllInboxMessagesDataSet().Tables[0].DefaultView;
};

dgUser1.Dispatcher.BeginInvoke(action);

Thanks in advance

有帮助吗?

解决方案

Thats easy. You should NEVER do blocking I/O on your UI thread.

SmsSender sms = new SmsSender();
DataView result = sms.GetAllInboxMessagesDataSet().Tables[0].DefaultView
Action action = () =>
{
    dgUser1.ItemsSource = result;
};
dgUser1.Dispatcher.BeginInvoke(action);

However this is actually NOT how you should write WPF apps. This pattern is done using WinForms like patterns. You should REALLY be using DataBinding.

Databinding would take care of all your Dispatcher calls.

其他提示

Dispatcher.BeginInvoke runs delegate on UI thread and since you have put complete action on dispatcher, it will be executed on UI thread which results in UI hang issue.

There are many ways to delegate time consuming operation on to background thread and dispatch UI calls on UI thread.

Simple example is to use BackgroundWorker. Put non-UI stuff in DoWork event handler and UI operation on RunWorkerCompleted handler which is called on UI thread only so need to dispatch calls to UI disptacher.

Small sample -

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork+=new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted +=
        new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
   dgUser1.ItemsSource = (DataView)e.Result;
}        

void worker_DoWork(object sender, DoWorkEventArgs e)
{
   SmsSender sms = new SmsSender();
   e.Result = sms.GetAllInboxMessagesDataSet().Tables[0].DefaultView;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top