【问题标题】:How to download image synchronously in background?如何在后台同步下载图片?
【发布时间】:2011-11-25 08:37:20
【问题描述】:

我有一个后台工作人员,我用它来从 Web 服务器获取一些数据。 还需要下载一些图像(png 或 jpg)。 但是每次我尝试在后台工作线程中创建 BitmapImage 或 WriteableBitmap 时,我都会得到 Invalid cross-thread access 是否可以在后台而不是 UI 线程中加载图像?

【问题讨论】:

  • 抱歉,以为是关于 android 的,请忽略此评论。我该如何删除 cmets?
  • 也许你可能会清楚为什么你认为你需要一个后台工作人员来做这件事。创建 BitmapImage 并为其指定 URL 不会在图像下载时阻塞线程。框架已经将其实现为异步操作。所以我不清楚为什么你需要“在后台同步”做一些事情?
  • 我正在编写一个从 Web 服务器检索一些信息的库。我希望它能够将所有数据保存到英镑数据库,以便即使没有互联网连接也可以恢复和上次检索的数据。因此,我只是运行库来收集所有信息并将其存储到 Sterling 的后台工作人员中。应该也可以在计划任务中使用这个库
  • 您尝试使用的类被设计为仅在 UI(调度程序)线程中使用,因此您要么必须编组回 UI 线程,要么以原始格式存储图像数据,并且仅在 UI 线程需要时创建此控件。

标签: c# silverlight windows-phone-7 silverlight-4.0


【解决方案1】:

使用它会为你工作。

Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    //write here whatever you want to update on screen.
                    textblock.Text = "text changed";
                    // just like this line changed the text of a textblock
                });

如果它不起作用,请粘贴您的代码。

【讨论】:

  • @user924780 不,这不是一种解决方法。问题是您无法访问位于其他线程中的对象,这将导致异常。有几种方法可以进行跨线程调用,这一种非常好。
  • @oleksii 很奇怪,为什么我在后台创建对象时它位于 UI 线程中? var image = new WritableBitmap(100, 100) 行抛出异常
  • @Sheldon:在 Silverlight 中,所有面向 UI 的类都特别限于主 UI 线程。甚至尝试在后台线程上构造这样的类都会导致异常。顺便说一句,即使如果您可以执行构造函数,生成的对象对您来说毫无用处,您将永远无法将其包含在 Silverlight VisualTree 中。
  • @AnthonyWJones 谢谢,现在很清楚了。我现在唯一的选择是将图像下载并保存为字节数组(
  • @Shedon:这实际上是有道理的。即使可以,我认为我也不想保留 UI 类的实例(这意味着所有额外的开销)。我会在后台/缓存/数据库中保留它的最简单表示,仅在即将使用它时将其水合为 UI 元素。请记住,下载的图像流将采用压缩格式,并且使用 imagetools 您甚至可以将 WriteableBitmap 中的像素数组转换为 PNG 用于存储目的。
【解决方案2】:

在 BackgroundWorker 的 DoWork 方法中,您无法访问在主线程中创建的控件,但在该方法中,您可以将下载的图像传递给 RunWorkerCompleted 事件方法,因为此事件在您创建 BackgroundWorker 的线程上运行(在大多数情况下,它是主线程)。

BackgroundWorker backgroundworker = new BackgroundWorker();
backgroundworker.DoWork += new DoWorkEventHandler(backgroundworker_DoWork);
backgroundworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundworker_RunWorkerCompleted);


static void backgroundworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //download image and make Image class instance
    e.Result = //assign your image here
}

static void backgroundworker_DoWork(object sender, DoWorkEventArgs e)
{
    Image i = (e.Result as Image);
    //assign image to your control
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多