WPF window 将文件发送到保管箱后冻结

WPF window freezing after sending file to dropbox

我的 window 在单击 "Send" 按钮后冻结。它发送文件然后它应该释放 GUI,但它没有。看我的代码:

    private void btn_send_Click(object sender, RoutedEventArgs e)
    {
        if (SBox.UploadFile("user", "service", 1, path.Text))
            MessageBox.Show("Success");
        else
            MessageBox.Show("Fail, try again");
    }

然后从 Sbox 编码 class:

    public static bool UploadFile(string user, string service, int orderId, string filepath)
    {
        DateTime now = DateTime.Now;
        dbx = new DropboxClient(login_key);

        string path = "/Files/" + user + "/" + service + "/order - " + orderId + "/received";
        string fileName = now.Year + "" + now.ToString("MM") + "" + now.ToString("dd") + "" + Path.GetExtension(filepath);

        Task upl = Upload(dbx, path, fileName, File.ReadAllBytes(filepath)); //send file
        upl.Wait();

        return true;
    }

和任务代码:

    static async Task Upload(DropboxClient dbx, string folder, string file, byte[] content)
    {
        using (var mem = new MemoryStream(content))
        {
            var updated = await dbx.Files.UploadAsync(
                folder + "/" + file,
                WriteMode.Overwrite.Instance,
                body: mem);
            Console.WriteLine("Saved {0}/{1} rev {2}", folder, file, updated.Rev);
        }
    }

如我所说,文件已发送到正确的文件夹,但 GUI 冻结。控制台应用程序完美运行,成功时写入输出。

您正在使用 Task.Wait()upl.Wait();

这会导致当前线程 运行 并等待任务完成后再继续。

编辑:

如果你想做的不仅仅是那个单一的方法(完成时执行其他操作),我总是使用这样的任务 Task.Run():

Task.Run(() =>
{
    Upload(...);
    OnCompletion();
}

如果你想做 UI 事情,记得在调度线程上调用它:

Task.Run(() =>
{
    Upload(...);
    Dispatcher.BeginInvoke(new Action(() => {
        OnCompletion();
    };
}

我确实玩了一下,也做了一些研究。这是我最后的工作代码 按钮:

    private async void btn_send_Click(object sender, RoutedEventArgs e)
    {
        SBox sbox = new SBox();
        progress.Text = "Uploading file, please wait...";
        bool t = await sbox.UploadFromGUI("user", "service", 1, path.Text);
        progress.Text = "";
        if (t == true)
            MessageBox.Show("Success!", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
        else
            MessageBox.Show("Failed", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    }

SBox 中的方法class:

    public async Task<bool> UploadFromGUI(string user, string service, int orderId, string filepath)
    {
        DateTime now = DateTime.Now;
        dbx = new DropboxClient(login_key);

        string path = "/files/" + user + "/" + service + "/order - " + orderId + "/received";
        string fileName = now.Year + "" + now.ToString("MM") + "" + now.ToString("dd") + "" + Path.GetExtension(filepath);

        try
        {
            using (var mem = new MemoryStream(File.ReadAllBytes(filepath)))
            {
                var updated = await dbx.Files.UploadAsync(
                    path + "/" + fileName,
                    WriteMode.Overwrite.Instance,
                    body: mem);
                return true;
            }
        }
        catch
        {
            return false;
        }
    }