后台工作人员仍然冻结 ui

Background worker still freezing ui

即使我设置了后台工作程序,我似乎也无法让它不冻结 UI。

我在网上四处寻找,但找不到解决方法。我已经尝试创建基本线程并且有效但我还需要在它运行时更新 UI 东西所以这就是我切换到 backgroundworkers 的原因,但是如果你能帮我弄清楚如何使用基本线程并让它工作没关系。

using MediaToolkit;
using MediaToolkit.Model;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using VideoLibrary;

namespace ConsoleApp1
{
public partial class Form1 : Form
{
    private List<VideoInfo> vids = new List<VideoInfo>();
    private List<VideoInfo> failedVids = new List<VideoInfo>();
    private int threads = 0;
    BackgroundWorker worker;
    private delegate void DELEGATE();
    static void Main(string[] args)
    {
        Form1 form = new Form1();
        form.ShowDialog();
    }

    public Form1()
    {
        InitializeComponent();
        worker = new BackgroundWorker();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if(threads == 0)
        {
            progressBar1.Maximum = vids.Count;
            progressBar1.Value = 0;
            failedVids.Clear();
            worker.DoWork += doWork;
            worker.RunWorkerAsync();
            //downloadVid();
        }else
        {
            Console.WriteLine("Waiting for threads" + threads);
        }
        /*Thread thread1 = new Thread(new ThreadStart(downloadVid));
        thread1.Start();*/
    }

    private void button1_Click_1(object sender, EventArgs e)
    {
        VideoInfo vid = new VideoInfo(tbLink.Text, tbTitle.Text, tbArtist.Text);
        vids.Add(vid);
        tbLink.Clear();
        tbTitle.Clear();
        listView1.Items.Add(vid.getLink());
    }

    private int downloadThread(int i)
    {
        Console.WriteLine(i);
        var source = @"C:\Users\derri\Downloads\DownloadTest\";
        var youtube = YouTube.Default;
        VideoInfo vidInfo = vids[(int) i];
        var vid = youtube.GetVideo(vidInfo.getLink());
        Console.WriteLine(vidInfo.getLink());
        try
        {
            File.WriteAllBytes(source + vid.FullName, vid.GetBytes());
        }
        catch (Exception e)
        {
            failedVids.Add(vids[(int)i]);
            Console.WriteLine(e);
            goto End;
        }

        var inputFile = new MediaFile { Filename = source + vid.FullName };
        var outputFile = new MediaFile { Filename = $"{source + vidInfo.getArtist() + " - " + vidInfo.getTitle()}.mp3" };

        using (var engine = new Engine())
        {
            engine.GetMetadata(inputFile);

            engine.Convert(inputFile, outputFile);
        }
        File.Exists(outputFile.Filename);
        File.Delete(inputFile.Filename);
        setTags(vidInfo.getArtist(), vidInfo.getTitle());
    End:
        threads--;
        return 1;
    }

    private void doWork(object sender, DoWorkEventArgs e)
    {
        Delegate del = new DELEGATE(downloadVid);
        this.Invoke(del);
    }

    private void downloadVid()
    {
        int prog = 0;
        for (int i = 0; i < vids.Count; i++)
        {
            Console.WriteLine(i);
            while ((threads > 5)) { }
            Thread thread = new Thread(() => { prog += downloadThread(i); });
            thread.Start();
            threads++;
            System.Threading.Thread.Sleep(1000);
            //thread.Join();
            /*ParameterizedThreadStart start = new ParameterizedThreadStart(downloadThread);
            Thread t = new Thread(start);
            t.Start(i);
            progressBar1.Value++;
            threads++;*/

        }

        while (threads > 0){}
        foreach (VideoInfo failedVid in failedVids)
        {
            listView2.Items.Add(failedVid.getLink());
        }
        listView1.Clear();
        vids.Clear();

    }

    private void setTags(string artist, string title)
    {
        TagLib.File file = TagLib.File.Create("C:\Users\derri\Downloads\DownloadTest\" + artist + " - " + title + ".mp3");
        file.Tag.Artists = (new String[] { artist });
        file.Tag.Title = (title);
        file.Save();
    }
}

}

this.Invoke 将在 UI 线程上 运行。

了解如何使用 BackgroundWorker class 的 ReportProgress 或 RunWorkerCompleted 事件。两者都允许您将数据从后台线程传递到 UI 线程。