好的,我当前的代码正在进行中,可能我会尝试使用Async CTP做同样的事情。但我仍然想了解发生了什么。
我有一个类似下面的功能
// In MainWindow.xaml.cs
Task.Factory.StartNew(() => helper.Send());
// In class HttpHelper
public void Send()
{
// ...
try
{
Status = Statuses.Uploading;
// write to request stream
Status = Statuses.Downloading;
// write to response stream
Status = Statuses.Idle; // the exception is thrown here
// ...
}
catch (Exception e)
{
// ...
}
}
HttpHelper
@pastebin 的完整代码。第76行Send()
我想知道为什么我会得到例外?也许我对线程做错了,但为什么只有在我成功设置Status
属性2次后才会引发异常?
我有一个事件处理程序,在1 if子句中侦听StatusChanged
事件,我忘了使用UI线程来更新UI
helper.StatusChanged += (s, evt) =>
{
_dispatcher.Invoke(new Action(() => txtStatus.Text = helper.Status.ToString())); // I used _dispatcher here correctly
if (helper.Status == HttpHelper.Statuses.Idle || helper.Status == HttpHelper.Statuses.Error)
progBar.IsIndeterminate = false; // but not here
};
答案 0 :(得分:3)
更新:我错过了您的代码中的(在我的辩护中,小)评论,该评论表明您使用的是WPF / Silverlight,而不是Windows Forms。
尽管如此,看起来你能够理解我所说的基本要点并将其应用到你自己的场景中(使用Dispatcher.Invoke
而不是Control.Invoke
) - 做得好;)
我猜测附加到StatusChanged
事件的事件处理程序会更新您的UI上的StatusLabel
控件?如果是这种情况,则需要从UI线程调用Invoke
; e.g:
void HttpHelper_StatusChanged(object sender, EventArgs e)
{
var httpHelper = (HttpHelper)sender;
UpdateStatus(httpHelper.Status);
}
void UpdateStatus(HttpHelper.Statuses status)
{
if (InvokeRequired)
{
Invoke(new Action<HttpHelper.Statuses>(UpdateStatus), status);
}
else
{
// Your code probably doesn't look like this;
// it's just an example.
statusLabel.Text = status.ToString();
}
}
你可能会看到两次失败后失败的原因有点超出我的意思;但我知道,当涉及到线程问题时,StatusLabel
控件尤其可能有点回避。我已经看到代码直接从后台线程更新(通常由于开发人员的遗忘),没有任何异常;在我看来,你只是幸运了两次而且运气不好。
答案 1 :(得分:0)
Status
会触摸用户界面吗?因为它看起来像。
我只能猜测,但我认为Status
会在UI上发生一些需要通过Dispatcher.Invoke()
进行更改的内容。
答案 2 :(得分:-1)
如果Status是一个全局变量,你会得到这个例外,因为多个线程同时访问和更新它。我建议用它锁一下