c# - 调用线程无法访问此对象,因为另一个线程拥有它

标签 c# .net wpf multithreading exception-handling

<分区>

为什么我不能在下面的代码中创建 CroppedBitmap?我有一个异常(exception):

The calling thread cannot access this object because a different thread owns it.

如果我把代码改成

CroppedBitmap cb = new CroppedBitmap(new WriteableBitmap(bf), new Int32Rect(1, 1, 5, 5));

异常消失了?为什么?

代码 1,cb.Freeze() 异常:

public MainWindow()
{
    InitializeComponent();

    ThreadPool.QueueUserWorkItem((o) =>
        {
            //load a large image file
            var bf = BitmapFrame.Create(
                new Uri("D:\\1172735642.jpg"),
                BitmapCreateOptions.None,
                BitmapCacheOption.None);
            bf.Freeze();
            Dispatcher.BeginInvoke(
                new Action(() =>
                    {
                        CroppedBitmap cb = new CroppedBitmap(bf, new Int32Rect(1,1,5,5));
                        cb.Freeze();
                        //set Image's source to cb....
                    }), 
                    DispatcherPriority.ApplicationIdle);
         }
    );
}

代码 2,有效:

    ThreadPool.QueueUserWorkItem((o) =>
    {
        var bf = BitmapFrame.Create(
                new Uri("D:\\1172740755.jpg"),
                BitmapCreateOptions.None,
                //BitmapCreateOptions.DelayCreation,
                BitmapCacheOption.None);
        bf.Freeze();
        var wb = new WriteableBitmap(bf);
        wb.Freeze();
        this.Dispatcher.Invoke(
            new Action(() =>
            {
                var r = new Int32Rect(1, 1, 5, 5);
                CroppedBitmap cb = new CroppedBitmap(wb, r);
                cb.Freeze();
                //set Image's source to cb....
                Image.Source = cb;
            }),
            DispatcherPriority.ApplicationIdle);
    }
);

代码 3,在没有 WritableBitmap 的情况下工作:

ThreadPool.QueueUserWorkItem((o) =>
    {
        var bf = BitmapFrame.Create(
                new Uri("D:\\1172735642.jpg"),
                BitmapCreateOptions.None,
                //BitmapCreateOptions.DelayCreation,
                BitmapCacheOption.None);
        bf.Freeze();
        var bf2 = BitmapFrame.Create(bf);
        bf2.Freeze();

        this.Dispatcher.Invoke(
            new Action(() =>
            {
                var r = new Int32Rect(1, 1, 5, 5);
                BitmapSource cb = new CroppedBitmap(bf2, r);
                cb.Freeze();
                //set Image's source to cb....
                Image.Source = cb;
            }),
            DispatcherPriority.ApplicationIdle);
    }
);

最佳答案

以下代码可能会帮助您解决从另一个线程更新 gui 元素的问题:

模块级别

delegate void updateCallback(string tekst);

这是更新元素的方法:

private void UpdateElement(string tekst)
{
    if (element.Dispatcher.CheckAccess() == false)
    {
        updateCallback uCallBack = new updateCallback(UpdateElement);
        this.Dispatcher.Invoke(uCallBack, tekst);
    }
    else
    { 
//update your element here
    }
 }

关于c# - 调用线程无法访问此对象,因为另一个线程拥有它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2728896/

相关文章:

c# - Windows 应用商店应用中的应用内购买问题

c# - 如何获取 Controller 名称和基本 Controller 中可用的数据?

.net - SqlBulkCopy 与 SqlBulkCopy 的比较TVP VS。 XML 参数对比20-200 个插入的单独插入过程?

.net - 带有附加属性的奇怪 WPF 错误

c# - 如何在没有我的 WPF 主机的情况下启动具有管理员权限的进程也以管理员权限运行以实现文件拖放?

c# - 具有回调的委托(delegate)的内存泄漏

c# - RichTextBlock 段落背景颜色

C# 版本兼容性

c# - 未调用 DataTemplate 中的命令

c# - 在 WPF 中取消设置/更改绑定(bind)