好,所以我正在开发游戏启动器。 它检查更新,如果存在,则将其下载并解压缩。 解压缩完成后,将新文件复制到需要的位置,然后删除zip和解压缩的文件。

问题是这样的:如果用户在解压缩时关闭启动器,则下次启动时,我在解压缩时遇到错误-该文件已存在。

所以我想做的是退出时删除Patch文件夹。 但是,如果后台工作程序正在运行,则无法删除该资源,因为该资源正被另一个进程使用。

下载器类:

static void downloader_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        if (!Directory.Exists(Path.Combine(BASE_DIR, "Patch")))
            Directory.CreateDirectory(Path.Combine(BASE_DIR, "Patch"));

        string sFilePathToWriteFileTo = Path.Combine(BASE_DIR, "Patch", "patch.zip").ToString();

        // first, we need to get the exact size (in bytes) of the file we are downloading
        Uri url = new Uri(sUrlToReadFileFrom);
        System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
        System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
        response.Close();
        // gets the size of the file in bytes
        Int64 iSize = response.ContentLength;

        // keeps track of the total bytes downloaded so we can update the progress bar
        Int64 iRunningByteTotal = 0;

        // use the webclient object to download the file
        using (System.Net.WebClient client = new System.Net.WebClient())
        {
            // open the file at the remote URL for reading
            using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
            {
                // using the FileStream object, we can write the downloaded bytes to the file system
                using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    // loop the stream and get the file into the byte buffer
                    int iByteSize = 0;
                    byte[] byteBuffer = new byte[1024];
                    double dTotal = (double)iSize;
                    while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
                    {
                        // write the bytes to the file system at the file path specified
                        streamLocal.Write(byteBuffer, 0, iByteSize);
                        iRunningByteTotal += iByteSize;

                        // calculate the progress out of a base "100"
                        double dIndex = (double)(iRunningByteTotal);
                        double dProgressPercentage = (dIndex / dTotal);
                        int iProgressPercentage = (int)(dProgressPercentage * 100);

                        // update the progress bar
                        worker.ReportProgress(iProgressPercentage);
                    }

                    // clean up the file stream
                    streamLocal.Close();
                }
                // close the connection to the remote server
                streamRemote.Close();
            }
        }

    }

然后解压缩:

private void decompresser_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        #region Unzip files

        if (!Directory.Exists(decompressPath))
            Directory.CreateDirectory(decompressPath);

        using (ZipArchive archive = ZipFile.OpenRead(archiveName))
        {
            int iTotal = archive.Entries.Count();
            int curr = 0;
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                if (entry.FullName != entry.Name)
                {
                    if (entry.Name == string.Empty)
                    {
                        //create folder here
                        Directory.CreateDirectory(Path.Combine(decompressPath, entry.FullName));
                    }
                    else
                    {
                        //create folder and extract file into it
                        string dirToCreate = entry.FullName.Replace(entry.Name, "");
                        Directory.CreateDirectory(Path.Combine(decompressPath, dirToCreate));
                        entry.ExtractToFile(Path.Combine(decompressPath, entry.FullName));
                    }
                }
                else
                {
                    //just extract file
                    Console.WriteLine(Path.Combine(decompressPath, entry.FullName));
                    entry.ExtractToFile(Path.Combine(decompressPath, entry.FullName));
                }

                curr++;
                var progress = ((double)curr / (double)iTotal) * 60.0;
                worker.ReportProgress((int)progress);
            }
        }

        //delete zip file
        File.Delete(Path.Combine(BASE_DIR, "Patch", "patch.zip"));
        #endregion

        #region Copy files
        string sourceDirName = Path.Combine(BASE_DIR, "Patch");
        string destDirName = BASE_DIR;
        DirectoryInfo dir = new DirectoryInfo(sourceDirName);
        long maxbytes = 0;
        List<FileInfo> files = new List<FileInfo>();
        FileInfo[] folder = dir.GetFiles("*.*", SearchOption.AllDirectories);
        foreach (FileInfo file in folder)
        {
            if ((file.Attributes & FileAttributes.Directory) != 0) continue;
            files.Add(file);
            maxbytes += file.Length;
        }

        // Copy files
        long bytes = 0;
        foreach (FileInfo file in files)
        {
            try
            {
                //where to copy
                string copyPath = file.FullName.Replace("Patch\\", "").Replace(file.Name, "");
                if (!Directory.Exists(copyPath))
                    Directory.CreateDirectory(copyPath);
                File.Copy(file.FullName, Path.Combine(copyPath, file.Name), true);
                var progress = 60 + ((double)bytes / (double)maxbytes) * 30.0;
                worker.ReportProgress((int)progress);
            }
            catch (Exception ex)
            {
            }
            bytes += file.Length;
        }

        #endregion

        #region Clean Up

        foreach (FileInfo file in files)
        {
            try
            {
                var progress = 90 + ((double)(maxbytes - file.Length) / (double)maxbytes) * 9;

                file.Delete();
                worker.ReportProgress((int)progress);
            }
            catch (Exception ex) { }
        }
        try
        {
            string delPath = Path.Combine(BASE_DIR, "Patch");
            Directory.Delete(delPath, true);
        }
        catch (Exception ex) { }

        worker.ReportProgress(100);


        #endregion
    }

我通过调用App.Current.Shutdown();终止应用程序App.Current.Shutdown(); 方法。

#1楼 票数:0

如果我什么都不缺,那么有一个非常简单的解决方案。 您可以通过调用workerObject.RequestStop();使用退出时事件停止所有后台工作程序workerObject.RequestStop(); (请注意,它仅向工作人员中的代码发出信号,要求您请求停止,您需要在工作人员的do work循环中进行处理以停止工作)。 然后,您可以清理补丁文件夹。

#2楼 票数:0

为了回避这个问题,您是否还不能在启动应用程序时而是在开始下载之前删除补丁程序文件夹?

#3楼 票数:0

@GWLlosa-我确实考虑过在启动时删除文件,如果需要的话,但是如果我找不到更好的方法,我将把它保存为万不得已

我尝试过这样的事情

    protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            updater.CancelAsync();
            while (updater.IsBusy)
            {
                Thread.Sleep(100);
            }
//run code to delete the files after the worked has stopped
}

但这只会使我陷入无限循环:)

#4楼 票数:0

如果这样做,我将在启动后立即发现并终止下载过程。

Process[] p = Process.GetProcessesByName("processname");
foreach (var proc in p)
{
     proc.Kill();
}

#5楼 票数:0

对于您的问题,我有2个解决方案。

1)不要试图在退出时删除补丁程序文件夹,只需启动并忘记BackgroundWorker,如果用户取消补丁程序并退出,则只需退出应用程序即可。 但是,总是在用户启动您的应用程序时删除补丁文件夹,特别是在您调用unzip之前。

2)如果您仍然想在退出时删除补丁文件夹,请使用CancelAsync()函数取消BackgroundWorker。 例如

private void btnStart_Click(object sender, EventArgs e)
{
    if (btnStart.Text == "Start")
    {
        ...
    }
    else
    {
        m_bgWorker.CancelAsync();
    }
}


private void SearchFiles(string strPath, string strPattern)
{
    string strMessage = "Parsing directory " + strPath;
    m_bgWorker.ReportProgress(0, strMessage);
    foreach (string strFileName in Directory.GetFiles(strPath, strPattern))
    {
        if (m_bgWorker.CancellationPending)
        {
            return;
        }
        else
        {
            m_lstFiles.Add(strFileName);
        }
    }

    foreach (string strDirName in Directory.GetDirectories(strPath))
    {
        if (m_bgWorker.CancellationPending)
        {
            return;
        }
        else
        {
            SearchFiles(strDirName, strPattern);
        }
    }
}

我从这篇文章中得到了代码。 您可以从该示例中阅读更多内容,以了解作者如何取消其BackgroundWorker。

  ask by m0rgul translate from so

未解决问题?本站智能推荐:

1回复

C#WPF应用程序的此线程/后台工作器设计可以吗?

作为在UI中使用线程等的新手,请问下面的简单设计似乎还可以。 参见链接图 尤其是: a)使用backgroundworker和backgroundworker ProgressChanged使聚合器在单独的线程上工作。 因此,我需要一个自定义类/类型,该类/类型具有将需要从聚合线
1回复

C#WPF程序在调试中运行,但未经调试不会释放

尝试在发布模式下测试小型程序,而不进行调试。 程序可以在调试模式下正常运行,在带有调试的释放模式下运行良好。 当我尝试在没有调试的情况下在发行版中运行时,会发生以下情况。 *注意:我已经尝试了多种配置模式。 对于x86和平台= x86以外的配置,x86给我带来了处理器架构错误。
1回复

使用c#wpf放大imageView图像

我试图创建一个窗口,其中包含“浏览”按钮来加载图像文件和一个按钮“+”来放大图像。 浏览按钮及其打开的对话框成功将图像加载到Image aka。 当我按下“+”按钮时,它不会放大加载的图像,但会使其模糊。 怎么了? 原始加载的图像名为OriginalSizedImage。 zoom
4回复

在关闭 C# WPF 应用程序之前询问用户

我想在关闭应用程序之前询问用户。 我正在使用 C# .NET 4.0 WPF。 我可以在 Windows 窗体中执行此操作,但不能在 WPF 中执行。 当用户想要关闭应用程序时会触发事件。 出现消息框,无论按下哪个按钮(是或否),应用程序始终关闭。 为什么? 错误在哪里? 它有效,但仅当用户按下“
4回复

关闭 C# WPF 应用程序中的所有窗口

我正在VS2013Express创建一个小 WPF 应用程序, VS2013Express我遇到了一个小问题。 你看,有三个窗口, MainWindow , LatAndLongDialog , TimeCitiesDialog 。 `LatAndLongDialog` 和 `TimeCit
3回复

延迟执行 - C#WPF

我有一个网格控件,点击每一行做一些后台工作来加载数据。 每个后台作业都在线程池线程上执行。 当用户快速点击项目时,许多加载数据的请求将排队。 我希望通过在单击每一行后提供延迟来最小化这一点。 在触发加载数据的请求之前会有一些延迟。 我正在考虑使用DispatcherTimer类。
1回复

匿名管道 c# WPF

我正在尝试使用在同一台机器上运行的两个 WPF 应用程序来实现 IPC。我需要使用 Winform实现类似于Example 的东西。 有人可以将以下代码转换为 WPF/C#,因为您可以看到委托调用直接依赖于 Winform Control, Wrapper 类的实现如下,
1回复

如何在C#WPF中使用多列下拉框?

我正在尝试在c#wpf中创建一个多列组合框,如下所示。 有任何想法吗? 当选择一行时,仅显示状态代码,但是所有详细信息都可以显示在下拉选择中。