【发布时间】:2013-11-19 21:25:44
【问题描述】:
我正在尝试构建一个小的图像小部件。它应该以启动画面启动,从 XML 列表加载图像,将它们放入对象内的列表中,然后关闭该表单并返回到 MainWindow。我在初始屏幕上使用了 BackgroundWorker,因此我可以根据需要退出。
据我所知,启动画面正在工作,至少列表的 Count 在 MainWindow 检查时显示其中包含对象。我遇到的问题是当我尝试访问列表中的对象时。然后我收到以下错误:调用线程无法访问此对象,因为另一个线程拥有它。
我已经尝试过 Delegates,一个静态对象,甚至将 MainWindow 的副本传递到 Splash 表单(这是我正在粘贴的版本)。但是,我无法解决这个问题。欢迎任何帮助。
Splash.xaml.cs
namespace Yvonne1
{
public partial class Splash : Window
{
public BackgroundWorker bw;
public string url = @"http://domain.com/pics-list.php";
public MainWindow mw;
public XmlNodeList xl;
public Splash()
{
InitializeComponent();
SetupWorker();
FetchXml();
progOne.Maximum = xl.Count;
bw.RunWorkerAsync();
}
private void SetupWorker()
{
bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
}
private void FetchXml()
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(this.url);
this.xl = doc.SelectNodes("//image");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
this.DialogResult = false;
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
bw.CancelAsync();
this.DialogResult = false;
}
public void bw_DoWork(object sender, DoWorkEventArgs e)
{
int xcount = 0;
foreach(XmlNode xn in xl)
{
string full = xn.FirstChild.InnerText;
string thumb = xn.LastChild.InnerText;
BitmapImage temp = new BitmapImage(new Uri(thumb));
mw.p1.New = new Piccy(full, thumb, temp);
xcount += 1;
bw.ReportProgress(xcount);
Thread.Sleep(200);
if (bw.CancellationPending == true)
{
e.Cancel = true; return;
}
}
}
public void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progOne.Value = Double.Parse(e.ProgressPercentage.ToString());
int done = int.Parse(progOne.Value.ToString()) - 1;
Piccy temp = mw.p1.Get(done);
txtStatus.Text = "Fetched: " + temp.Thumb;
}
public void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (progOne.Value == progOne.Maximum)
{
this.DialogResult = true;
}
}
}
}
MainWindow.xaml.cs(有错误的部分。)
private void StartUp()
{
try
{
MessageBox.Show(p1.Count.ToString());
Piccy temp = p1.Get(1);
imgMain.Source = temp.Img;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message+"\n\n"+ex.Source+"\n\n"+ex.StackTrace, "Error");
}
}
imgMain.Source = temp.Img; 行是线程错误出现的地方。
提前致谢。
更新:BitmapImage temp = new BitmapImage(new Uri(thumb)); 行是问题所在。谢谢。
【问题讨论】:
-
google.com.au/…的可能重复
-
TLDR; ta.speot.is 链接,除非您使用 FromCurrentSynchronizationContext,否则您无法在后台线程中更改绑定在 UI 线程上的集合
-
并且BitmapImage绑定到UI线程。我才意识到这一点。
标签: c# wpf multithreading backgroundworker