使用BackgroundWorker时,UI线程仍然挂起

时间:2015-01-25 15:04:36

标签: c# wpf multithreading com backgroundworker

由于此处描述的问题:

WPD MTP stream hangs on commit

尽管使用BackgroundWorker进行呼叫,但我的WPF程序的UI处于挂起状态(意味着它在执行某项任务时无响应)。我已经读过一些关于这个事实的事实,即执行操作的COM对象是在UI线程上创建的,但是当我打破挂起的代码时,我发现它实际上是在执行的一个WorkerThread而不是MainThread,这似乎表明这不是问题(虽然我是一个线程新手)。

任何人都可以解释为什么会发生这种情况以及我应该如何解决这个UI问题?

相关代码:

从基类开始设置backgroundworker:

public void Sync()
{
    SyncBackgroundWorker.WorkerReportsProgress = true;
    SyncBackgroundWorker.WorkerSupportsCancellation = true;
    SyncBackgroundWorker.DoWork += SyncBackgroundWorker_DoWork;
    SyncBackgroundWorker.ProgressChanged += SyncBackgroundWorker_ProgressChanged;
    SyncBackgroundWorker.RunWorkerCompleted += SyncBackgroundWorker_RunWorkerCompleted;

    SyncBackgroundWorker.RunWorkerAsync();
}

protected void SyncBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    // Retrieve needed files from iTunes and compose m3u playlists
    var syncInfo = this.getSyncInfo();

    // Save m3u files to music root on target
    this.saveM3UPlaylists(syncInfo.M3Us);
}

从扩展基类的类(最后一行启动文件副本):

protected override void saveM3UPlaylists(List<FileInfo> M3UPlaylists)
{
    foreach (var file in this.Folder.GetFiles())
    {
        if (file.Extension == ".m3u")
            file.Delete();
    }

    int numPlaylists = this.Playlists.Count;
    for (int i = 0; i < numPlaylists; i++)
        PortableDevices.PortableDeviceFile.CopyFileToDevice(this.Folder, makeValidFileName(this.Playlists[i].Name + ".m3u"), M3UPlaylists[i]);
}

来自相关便携设备类。 targetStream.Commit(0)部分导致实际冻结,如前面给出的链接中所述。请注意,在程序开始时,在设置与设备的连接时,先前已初始化COM对象(IPortableDevice)parent.Device.Content

public static void CopyFileToDevice(PortableDeviceFolder parent, string name, FileInfo file)
{
    IPortableDeviceValues values = GetRequiredPropertiesForContentType(parent.Id, name, file.Length);

    PortableDeviceApiLib.IStream tempStream;
    uint blockSize = 0;
    parent.Device.Content.CreateObjectWithPropertiesAndData(
        values,
        out tempStream,
        ref blockSize,
        null);

    System.Runtime.InteropServices.ComTypes.IStream targetStream =
        (System.Runtime.InteropServices.ComTypes.IStream)tempStream;
    try
    {
        using (var sourceStream = file.OpenRead())
        {
            var buffer = new byte[blockSize];
            int bytesRead;
            do
            {
                bytesRead = sourceStream.Read(buffer, 0, (int)blockSize);
                targetStream.Write(buffer, bytesRead, IntPtr.Zero);
            } while (bytesRead > 0);
        }

        targetStream.Commit(0);
    }
    finally
    {
        Marshal.ReleaseComObject(tempStream);
    }
    parent.Refresh();
}

0 个答案:

没有答案