我正在尝试在线程在后台运行时为加载屏幕制作动画,但它不起作用。
我意识到它与调用Button.Dispatcher的backgroundworker有关,但是我无法删除它,因为它会导致线程错误。我该怎么做才能解决这个问题?
下面是我的代码:
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
Storyboard sb = (Storyboard)FindResource("Loading");
sb.Dispatcher.BeginInvoke(new Action(() => sb.Begin()), DispatcherPriority.Normal, null);
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerAsync();
}
private void bg_DoWork(object sender, DoWorkEventArgs e)
{
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(RunThread));
thread.Start();
}
private void RunThread()
{
btnLogin.Dispatcher.BeginInvoke(new Action(() => TheBackgroundWork()), DispatcherPriority.Normal, null);
}
更新
我按照Jay的建议从Do_Worker中删除了UI调用。不幸的是我仍然收到错误:
The calling thread cannot access this object because a different thread owns it.
我的网络服务客户端
抛出了它下面是更新的代码:
private WebServiceClient proxy = new WebServiceClient();
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
sb = (Storyboard)FindResource("sbLoading");
sb.Dispatcher.BeginInvoke(new Action(() => sb.Begin()), DispatcherPriority.Normal, null);
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
bg.RunWorkerAsync();
}
private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
var u = e.Result;
if (u != null)
//pass the data
}
private void bg_DoWork(object sender, DoWorkEventArgs e)
{
try
{
var u = proxy.ToWebService(x,y); //this guy throws an error
e.Result = u;
}
catch
{
this.Dispatcher.Invoke(new Action(
() => MessageBox.Show("Connection Error", this.Title)),
DispatcherPriority.Normal, null);
}
}
答案 0 :(得分:1)
bg_DoWork
方法已经在后台线程上运行,因此无需在其中创建线程。bg_DoWork
中的任何内容都不应触及UI元素或任何数据绑定到UI元素。如果您有一些返回数据,请将其打包到一个对象中并将其填入DoWorkEventArgs.Result
属性。BackgroundWorker.RunWorkerCompleted
事件添加另一个处理程序。此方法将在UI线程上运行,因此您可以从RunWorkerCompletedEventArgs
读取响应数据(这将是您在#2中指定的结果对象)并根据需要更新UI。 BackgroundWorker
的美妙之处在于它将处理线程创建和数据封送回UI线程 - 不需要任何Dispatcher.Invoke
。
为了响应您的编辑,Web服务调用可能会抛出异常,但是您获得的线程异常是由尝试从后台线程访问this
引起的。
正如您必须将成功结果打包在DoWorkEventArgs.Result
中一样,您也需要在此处打包失败结果。
您传回的对象可以是任何内容,因此您可以添加bool Success
属性,Exception CaughtException
属性,等内容。
您将在RunWorkerCompleted
处理程序中检查这些值,这是您展示MessageBox
的位置。