簡體   English   中英

無法將邏輯與主線程分開時,如何設置BackgroundWorker(或替代方法)?

[英]How do I set up a BackgroundWorker (or alternative) when I can't separate the logic from the main thread?

我需要為wpf中的進度欄​​使用backgroundworker,而我是C#的新手。 我已經閱讀了很多有關它們的文章,並且看到可以創建一個backgroundWorker,並將需要跟蹤的邏輯移動到DoWork方法中,但是我似乎無法分離這些邏輯。 任何幫助表示贊賞。

編輯這是我實際上從更大的程序中遇到的一個問題。 我知道,有一個將數字相乘的背景是一個壞主意。 這只是我能提出的最小問題,它顯示了我遇到的問題。 /編輯

該程序只使用兩組數字並將它們相乘,但是我想在一個單獨的線程中使用一個進度條,該進度條與一個顯示我已完成百分比的MessageBox同時更新,並使用這些值更新一個textBlock。

MainWindow.xaml.cs

namespace backgroundWorkersWPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            double[] group1 = { 1, 2, 3, 4 };
            double[] group2 = { 5, 6, 7, 8 };

            double multipliedNumbers = 0;

            double totalCount = group1.Count() * group2.Count();
            double percentageDone = 0;

            double steps = 0;

            foreach (double x in group1)
            {

                foreach (double y in group2)
                {
                    multipliedNumbers = x * y;


                    txtBlock.Text = multipliedNumbers.ToString();

                    steps++;

                    /*I need this part in a separate thread, but I don't know 
how to easily move this log to a DoWork method without moving everything.*/
                    percentageDone = steps / totalCount * 100;
                    progBar.Value = percentageDone;

                    /*So, if the above part were in a separate thread, 
hopefully I would see my MainWindow with a textblock showing the 
current multiplication value, a messagebox that reports a numerical value
for the percentage, and a progress bar that changes percentage every time 
I close the messagebox. */
                    MessageBox.Show(percentageDone.ToString());
                }
            }
        }
    }
}

MainWindow.xaml

<Window x:Class="backgroundWorkersWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock Name="txtBlock"/>
        <ProgressBar Height="20"
                     Width="Auto"
                     Minimum="0"
                     Maximum="100"
                     Name="progBar"/>


    </Grid>
</Window>

回顧一下,現在發生的事情是,由於所有內容都在一個線程中,因此我的MessageBox出現了,並計算了百分比,然后當它達到100%時,它將打開MainWindow並顯示完整的進度欄,並且textBlock顯示對相乘的最后兩個數字的答案。

我想發生的是,進度條在單獨的線程中運行,而其他所有內容都保留在當前線程中。

我以為我需要創建一個BackgroundWorker,並以某種方式將更新的完成百分比值發送給它,但是我只能找到將所有邏輯移入其中的簡單背景工作人員示例。

編輯為了澄清起見,我說過我只想要新線程中的進度條,但是我不介意是否還有其他內容,例如計算也可以在新線程中進行。 我只是無法添加后台工作程序,而不能完全弄亂程序,或者將所有邏輯都移到另一個線程。 我將添加一些代碼以顯示過去發生的錯誤類型以及我不想要的錯誤。 /編輯

我不認為這是重復的,因為...我不認為這是重復的,因為我不是在問如何設置BackgroundWorker,而是在問我應該如何分離邏輯。 例如。

我有一個嵌套的循環。 對我來說,創建一個BackgroundWorker並讓我的DoWork方法僅具有兩個for循環就很簡單。 但是這些循環中有邏輯,我不想在單獨的線程上使用。 我是新手,所以我可能會錯誤地提出問題,但我覺得好像問如何分隔此邏輯與如何使用后台工作人員是一個不同的問題。

編輯

我找到了適合我的解決方案。 我知道當前已將其標記為重復,但是無論如何我還是要添加我的解決方案,以防萬一有人偶然發現此問題並試圖找出C#線程。

要回答我的問題,分離邏輯就像創建新函數一樣簡單。 我真的不明白后台工作者的工作方式,這是我的問題。 我不確定如何在后台划分出我需要的數據。 我在了解有關異步/等待的更多信息時找到了解決方案。 異步/等待對我來說更有意義,因此更容易理解,事實證明,在大多數情況下,應該在BackgroundWorkers上使用它。 所以這是我的解決方案。 希望最終將其打開。

MainWindow.xaml

<Window x:Class="backgroundWorkersWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock Name="txtBlock"/>
        <ProgressBar Height="20"
                     Width="Auto"
                     Minimum="0"
                     Maximum="100"
                     Name="progBar"/>
        <TextBlock Name="percentage"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center"
                   />


    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace backgroundWorkersWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            double[] group1 = { 1, 2, 3, 4 };
            double[] group2 = { 5, 6, 7, 8 };



            //Now the work I wanted is going to an async function.  And the data I need in the main thread is returned using IProgress<>
            doWork(group1, group2);


        }

        private async void doWork(double[] group1, double[] group2)
        {

            double percentageDone = 0;
            double steps = 0;
            double multipliedNumbers = 0;
            double totalCount = group1.Count() * group2.Count();

            foreach (double x in group1)
            {

                foreach (double y in group2)
                {
                    multipliedNumbers = x * y;


                    txtBlock.Text = "Multiplied Numbers: " + x + " * " + y + " = " + multipliedNumbers.ToString();

                    steps++;

                    var progress = new Progress<int>(updateProgressBar);
                    await System.Threading.Tasks.Task.Factory.StartNew(() => calculatePercentage(steps, totalCount, percentageDone, progress));

                }
            }
        }
        private void calculatePercentage(double steps, double totalCount, double percentageDone, IProgress<int> progress)
        {
            percentageDone = steps / totalCount * 100;
            progress.Report((int)percentageDone);
            MessageBox.Show(percentageDone.ToString());

        }
        private void updateProgressBar(int percentageDone)
        {
            progBar.Value = percentageDone;
            percentage.Text = percentageDone.ToString() + "%";
        }
    }
}

/編輯

您可以通過調用主線程來更新BackgroundWorker中的UI元素。 您可以執行以下操作:

            double[] group1 = { 1, 2, 3, 4 };
            double[] group2 = { 5, 6, 7, 8 };

            double multipliedNumbers = 0;

            double totalCount = group1.Count() * group2.Count();
            double percentageDone = 0;

            double steps = 0;


            var bworker = new BackgroundWorker();
            bworker.DoWork += (s, e) =>
            {
                foreach (double x in group1)
                {

                    foreach (double y in group2)
                    {
                        multipliedNumbers = x * y;
                        steps++;

                        this.Invoke((MethodInvoker)delegate()
                        {
                            txtBlock.Text = multipliedNumbers.ToString();
                            percentageDone = steps / totalCount * 100;
                            progBar.Value = percentageDone;
                        });
                    }
                }
            };
            bworker.RunWorkerAsync();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM