首页 > 解决方案 > BackgroundWorker:Argument-Object 的子代

问题描述

我正在开发一个运行平稳的 WPF 应用程序,直到我添加了线程。我想通过将保存/自动保存过程放入 a 中来简化保存/自动保存过程, BackgroundWorker这样我的 UI 在保存时不会被阻塞。

将我的应用程序视为自定义相册制作器。假设我的 UI 由几个图像对象组成。这些图像的来源位于自定义中PhotobookImageObject,因为每个选定的图像还包含其他元数据。

PhotobookImageObject

public class PhotobookImageObject
{
    public BitmapSource source { get; set; }
    public String unimportantMetadata{ get; set; }       
}

当我想保存时,我想保存完整的相册。为简单起见:

写真集

public class Photobook: INotifyPropertyChanged
    {
        public List<PhotobookImageObject> Photos{ get; set;}
        public String otherMetaData { get; set;}
    }

我的保存过程在不使用线程时有效。但是自从我在其中运行它之后,BackgroundWorker 我就无法再访问它 PhotobookImageObjectslist

现在我知道用于保存的线程无法访问来自不同线程的对象。这就是为什么我使用自定义类将对象推送到 BackgroundWorker 的线程中。我在这里找到了这个解决方案:How do you pass a List<> of Lists<> to a background worker?

这是实际代码:

设置工人:

private static BackgroundWorker saveWorker = new BackgroundWorker();


private static void saveWorkerExec(Photobook book, String Location, bool notAuto)
            {
                saveWorker.DoWork += doWork;
                saveWorker.WorkerSupportsCancellation = true;
                saveWorker.RunWorkerCompleted += (s, o) =>
                {
                    Helper.Message("Photobook saved");
                    if (o.Error != null)
                    {
                        MessageBox.Show("There was an error while saving! \n\n" + o.Error.ToString());
                    }
                };
                BGObj obj = new BGObj
                {
                    bk = book,
                    Loc = Location,
                    not = notAuto
                };
                saveWorker.RunWorkerAsync(obj);
            }

我用来传输数据的自定义类:

 public class BGObj
        {
            public Photobook bk { get; set; }
            public String Loc { get; set; }
            public bool not { get; set; }
        }

BackgroundWorker以及应该将类接收到他自己的线程中的实际部分:

    private static void doWork(object sender, DoWorkEventArgs e)
    {
        BGObj received = e.Argument as BGObj;
        Photobook book= received.bk;
        String Location = received.Loc;
        bool notAuto = received.not;
        
        //this function can not Access the books.Photos.last().source for example.
        SaveProjectToContainer(book, Location, notAuto);
    }

我仍然收到一个系统。当我InvalidOperationException尝试访问BitmapSource.PhotobookImageObjectPhotosPhotobook

我的假设:BGobj我正在创建的只是引用实际的 Photobook,因此其成员的数据仍然存在于错误的线程中。我到底如何才能确保我的对象的所有子成员实际上都传递给我想要处理它们的线程?还是我在这里错了,还有别的?

感谢您的时间。

标签: c#wpfmultithreadingbackgroundworker

解决方案


由于没有人可以帮助我解决这个问题,我遵循 Theodors 的方法并使用Async/Await.

据我了解,这不是让动作在后台运行,而是await在线程有可用容量时释放 UI 线程并运行“中间任务”。这允许我访问 UI 元素并仍然停止应用程序冻结有点同时自动保存。

如果有人需要一些提示如何解决这个问题,可以这样想:

public static void NotMain()
{
// queue following function. void Main for example would continue running after this.
await do_stuff_in_between(var object);
// Stuff after await will only happen if the function is done but UI is not blocked
Console.WriteLine("saving done");
}

public static async Task do_stuff_in_between(var object)
{
// do stuff with object or whatever you want.
}

推荐阅读