长时间运行 - 使用BitmapImage更新UI不起作用

时间:2012-03-04 06:57:45

标签: wpf multithreading c#-4.0 visual-c#-express-2010

我很沮丧地试图解决这个问题。为什么在完成后创建线程并更新UI 如此复杂?!我已经尝试了thisthisthis,但我仍然无法清楚地了解整个多线程事物。在Java中这很容易......

无论如何,这是我的代码的简化版作为第三个链接的结果:

private delegate void SimpleDelegate2(BitmapImage bi);
private delegate void SimpleDelegate(string st1, string st2);

private void Process(string st1)
{
    try
    {
        string st2 = "test st2";
        SimpleDelegate del = new SimpleDelegate(LongRunningProcess);
        del.BeginInvoke(st1, st2, null, null);
    }
    catch
    {
        //do some failsafe thing
    }
}

private void LongRunningProcess(string st1, string st2)
{
    //do some long processing with the strings
    BitmapImage bi = new BitmapImage();//there will be an actual bitmap here

    SimpleDelegate2 del1 = delegate(BitmapImage bimg)
    {
        ImageControlOnWPFform.Source = bimg; //null;
    };
    this.Dispatcher.BeginInvoke(DispatcherPriority.Send, del1, bi);
}

此处的问题是我无法将图片控件的Source值设置为bimg ,但我可以将其设置为null每当我尝试将其设置为bimg我得到的异常是说调用线程无法访问此对象,因为另一个线程拥有它。我也尝试将其直接设置为bi,这也会产生相同的异常。

但我可以将源设置为null而没有任何问题,这意味着我可以修改Image控件的Source值。但是,如何访问bibimg?我做错了吗?

另外:我注意到上一个BeginInvoke的给定参数与方法的任何重载都不匹配,但是它们仍然被认为是有效的并且有效正常。当我指向BeginInvoke时,我显示的方法重载集完全不同于在方法名称后键入(时出现的方法重载集。为什么呢?

1 个答案:

答案 0 :(得分:2)

回答主要问题

在UI线程中使用bi.Freeze()之前执行BitmapImageFreeze操作将使BitmapImage为只读且线程安全。

    ...
    //do some long processing with the strings
    BitmapImage bi = new BitmapImage();//there will be an actual bitmap here
    bi.Freeze();

    SimpleDelegate2 del1 = delegate(BitmapImage bimg)
    ...

回答

班级System.Windows.Threading.Dispatcher有五个BeginInvoke方法签名:

public DispatcherOperation BeginInvoke(Delegate method, params object[] args);
public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method);
public DispatcherOperation BeginInvoke(Delegate method, DispatcherPriority priority, params object[] args);
public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method, object arg);
public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method, object arg, params object[] args);

但是,其中三个签名(DispatcherPriority priority作为第一个参数的签名)上面有以下标记:

[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]

这就是为什么在方法名称后输入(时它们不显示的原因。