Не до конца выполняется BackgroundWorker. C#

142
18 апреля 2022, 09:00

Есть BackgroundWorker который выполняет некий код. После окончания работы, он должен написать переменную в label. Но это не происходит. Тогда я решил разбить код в BackgroundWorker на маленькие кусочки, после выполнения кусочка кода выводится число кусочка (Console.WriteLine), их всего 8. Первый семь - это проверка условий, последний - вывод. То когда я скомпилировал программу, то в выводе увидел:

1
2
3
4
5
6
7

C чем это связано?

Код воркера:

private void RegistryChecker_DoWork(object sender, DoWorkEventArgs e)
        {
            int CanOptimisated = 0;
            var printers = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\RemoteComputer\NameSpace\{863aa9fd-42df-457b-8e4d-0de1b8015c60}");
            //var onedrive = Registry.LocalMachine;
            string unloaddlls = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer";
            string superfetch = @"SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters";
            string prioritycontrol = @"SYSTEM\CurrentControlSet\Control\PriorityControl";
            string disableexecuting = @"SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management";
            string enablesmartscreen = @"SOFTWARE\Policies\Microsoft\Windows\System";
            Console.WriteLine(1);
            try
            {
                printers.GetValue("");
                CanOptimisated++;
                guna2CheckBox1.Invoke(new Action(() =>
                {
                    guna2CheckBox1.Enabled = true;
                }));
            }
            catch
            {
                guna2CheckBox1.Invoke(new Action(() =>
                {
                    guna2CheckBox1.Enabled = false;
                }));
            }
            Console.WriteLine(2);
            if (CheckRegistry(unloaddlls, "AlwaysUnloadDll", "1") == true)
            {
                guna2CheckBox2.Invoke(new Action(() =>
                {
                    guna2CheckBox2.Enabled = false;
                }));
            }
            else
            {
                CanOptimisated++;
                guna2CheckBox2.Invoke(new Action(() =>
                {
                    guna2CheckBox2.Enabled = true;
                }));
            }
            Console.WriteLine(3);
            if (CheckRegistry(superfetch, "EnableSuperfetch", "0") == true)
            {
                guna2CheckBox4.Invoke(new Action(() =>
                {
                    guna2CheckBox4.Enabled = false;
                }));
            }
            else
            {
                CanOptimisated++;
                guna2CheckBox4.Invoke(new Action(() =>
                {
                    guna2CheckBox4.Enabled = true;
                }));
            }
            Console.WriteLine(4);
            if (CheckRegistry(superfetch, "EnablePrefetcher", "0") == true)
            {
                guna2CheckBox5.Invoke(new Action(() =>
                {
                    guna2CheckBox5.Enabled = false;
                }));
            }
            else
            {
                CanOptimisated++;
                guna2CheckBox5.Invoke(new Action(() =>
                {
                    guna2CheckBox5.Enabled = true;
                }));
            }
            Console.WriteLine(5);
            if (CheckRegistry(prioritycontrol, "Win32PrioritySeparation", "6") == true)
            {
                guna2CheckBox6.Invoke(new Action(() =>
                {
                    guna2CheckBox6.Enabled = false;
                }));
            }
            else
            {
                CanOptimisated++;
                guna2CheckBox6.Invoke(new Action(() =>
                {
                    guna2CheckBox6.Enabled = true;
                }));
            }
            Console.WriteLine(6);
            if (CheckRegistry(disableexecuting, "DisablePagingExecutive", "1") == true)
            {
                guna2CheckBox7.Invoke(new Action(() =>
                {
                    guna2CheckBox7.Enabled = false;
                }));
            }
            else
            {
                CanOptimisated++;
                guna2CheckBox7.Invoke(new Action(() =>
                {
                    guna2CheckBox7.Enabled = true;
                }));
            }
            Console.WriteLine(7);
            if (CheckRegistry(enablesmartscreen, "EnableSmartScreen", "0") == true)
            {
                guna2CheckBox8.Invoke(new Action(() =>
                {
                    guna2CheckBox8.Enabled = false;
                }));
            }
            else
            {
                CanOptimisated++;
                guna2CheckBox8.Invoke(new Action(() =>
                {
                    guna2CheckBox8.Enabled = true;
                }));
            }
            Console.WriteLine(8);
            label9.Invoke(new Action(() =>
            {
                label9.Text = CanOptimisated + " Пунктов";
            }));
        }
        bool CheckRegistry(string path, string nameValue, string value)
        {
            var path1 = Registry.LocalMachine.OpenSubKey(path);
            if (path1.GetValue(nameValue).ToString() == value)
            {
                path1.Close();
                return true;
            }
            else
            {
                path1.Close();
                return false;
            }
        }

Метод, который запускает воркера:

 private void Form1_Load(object sender, EventArgs e)
        {
            guna2GradientCircleButton2.PerformClick();
            RegistryChecker.RunWorkerAsync();
        }
Answer 1

Наиболее вероятно, что внутри воркера у вас возникает исключение, которое вы не отлавливаете, но так как оно выполняется в не основном потоке, и этим основным потоком никак не ожидается, то возникшее исключение проваливается в бездну, вы просто его не видите.

Избежать этого можно используя более современный подход к параллельным вычислениям и асинхронным операциям.

private async void Form1_Load(object sender, EventArgs e)
{
    IProgress<Action> callback = new Progress<Action>(action => action()); // заменитель инвока
    try
    {
        guna2GradientCircleButton2.PerformClick();
        await Task.Run(() => RegistryChecker(callback));
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}
private void RegistryChecker(IProgress<Action> status)
{
    int CanOptimisated = 0;
    //var onedrive = Registry.LocalMachine;
    const string printerspath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\RemoteComputer\NameSpace\{863aa9fd-42df-457b-8e4d-0de1b8015c60}";
    const string unloaddlls = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer";
    const string superfetch = @"SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters";
    const string prioritycontrol = @"SYSTEM\CurrentControlSet\Control\PriorityControl";
    const string disableexecuting = @"SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management";
    const string enablesmartscreen = @"SOFTWARE\Policies\Microsoft\Windows\System";
    Debug.WriteLine(1); // используйте вместо Console в GUI приложениях
    bool check1 = false;
    try
    {
        // RegistryKey - IDisposable, с ним можно вот так.
        using (RegistryKey printers = Registry.LocalMachine.OpenSubKey(printerspath))
        {
            printers.GetValue("");
        }
        CanOptimisated++;
        check1 = true;
    }
    catch { }
    status.Report(() => guna2CheckBox1.Enabled = check1); // было 15 инвоков, стало 8
    Debug.WriteLine(2);
    bool check2 = !CheckRegistry(unloaddlls, "AlwaysUnloadDll", "1");
    if (check2)
        CanOptimisated++;
    status.Report(() => guna2CheckBox2.Enabled = check2);
    Debug.WriteLine(3);
    bool check4 = !CheckRegistry(superfetch, "EnableSuperfetch", "0");
    if (check4)
        CanOptimisated++;
    status.Report(() => guna2CheckBox4.Enabled = check4);
    Debug.WriteLine(4);
    bool check5 = !CheckRegistry(superfetch, "EnablePrefetcher", "0");
    if (check5)
        CanOptimisated++;
    status.Report(() => guna2CheckBox5.Enabled = check5);
    Debug.WriteLine(5);
    bool check6 = !CheckRegistry(prioritycontrol, "Win32PrioritySeparation", "6");
    if (check6)
        CanOptimisated++;
    status.Report(() => guna2CheckBox6.Enabled = check6);
    Debug.WriteLine(6);
    bool check7 = !CheckRegistry(disableexecuting, "DisablePagingExecutive", "1");
    if (check7)
        CanOptimisated++;
    status.Report(() => guna2CheckBox7.Enabled = check7);
    Debug.WriteLine(7);
    bool check8 = !CheckRegistry(enablesmartscreen, "EnableSmartScreen", "0");
    if (check8)
        CanOptimisated++;
    status.Report(() => guna2CheckBox8.Enabled = check8);
    Debug.WriteLine(8);
    status.Report(() => label9.Text = CanOptimisated + " Пунктов");
}
private bool CheckRegistry(string path, string nameValue, string value)
{
    // этот метод тоже немного упростился
    using (RegistryKey path1 = Registry.LocalMachine.OpenSubKey(path))
    {
        return path1.GetValue(nameValue).ToString() == value;
    }
}

Проверьте этот код, он должен либо точно отработать, либо точно вернуть ошибку. Эту стену повторяющегося кода можно еще упростить, засунув в цикл, но я не стал изменять ваш код до неузнаваемости, а просто сократил.

Как вы уже поняли, BackgroundWorker больше не нужен.

READ ALSO
Привязка данных в DataGridView

Привязка данных в DataGridView

Возникла такая проблемаУ меня есть моя структура:

156
Как окончательно сохранить ассет Scriptable object в Unity3d?

Как окончательно сохранить ассет Scriptable object в Unity3d?

В моей игре есть ассет со статистикойВ течение одной сессии всё работает прекрасно, данные спокойно перетекают по сценам

129
BackgroundService не может корректно завершиться

BackgroundService не может корректно завершиться

Не могу понять, почему мой BackgroundService (NET Core 3

164
C# переписать строку в файле

C# переписать строку в файле

Пользователь создаёт запись в файлеДалее, если нужно, он может переписать нужную запись

141