封闭块中的变量在匿名函数中变为空

Jan*_*Jan 2 c# wpf null multithreading anonymous-function

var client = new WebClient();
var bytes = client.DownloadData(webUrl); <-- NOT null

Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
    BitmapImage img = new BitmapImage();
    img.BeginInit();
    img.StreamSource = new MemoryStream(bytes); <-- null
    img.EndInit();
    img_DownloadCompleted(img, webUrl);
}));
Run Code Online (Sandbox Code Playgroud)

上述代码在线程中执行,以避免阻止UI.

我试图将图像从互联网下载到BitmapImage对象中.图像下载正确,但当我尝试在我的UI(使用Dispatcher.Invoke)中使用它时,我收到此错误消息:The calling thread cannot access this object because a different thread owns it.

所以我添加了在UI线程上创建图像的代码.但是现在,当代码到达<-- null变量bytes所指示的行时突然变为空.在执行进入匿名函数之前它不为null.(我查看了调试器)

有人知道为什么吗?谷歌不是很有帮助.

更改变量类型的bytes,以var不作任何区别.

Ale*_*kov 5

您很可能bytes稍后更改变量,因此修改匿名函数内的"捕获"值.就像是:

var bytes = client.DownloadData(webUrl); <-- NOT null
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
 ...  img.StreamSource = new MemoryStream(bytes); <-- null
 ...
}
bytes = null; // something like this - because why not? 
Run Code Online (Sandbox Code Playgroud)

请注意,即使代码如下顺序和img.StreamSource = ... bytes = null;行,它实际上可能会以相反的顺序执行(不确定性,因为它可以运行在其他线程).

您应该非常小心这些捕获将在稍后/在其他线程上异步执行.更安全的选项是在单独的方法中创建匿名函数,以便您以后不能更改捕获的变量:

Action CreateBitmapAction(bytes[] bytes)
{
 return () =>
 {
    BitmapImage img = new BitmapImage();
    img.BeginInit();
    img.StreamSource = new MemoryStream(bytes);
    img.EndInit();
    img_DownloadCompleted(img, webUrl);
 };
}

Application.Current.Dispatcher.BeginInvoke(CreateBitmapAction(bytes));
Run Code Online (Sandbox Code Playgroud)