Как синхронизировать несколько фоновых рабочих классов в wpf? - PullRequest
0 голосов
/ 10 января 2012

Я реализовал фоновый рабочий класс, похожий на приведенный ниже пример, и я хочу обновлять свой интерфейс каждый раз, когда фоновый рабочий завершается.

          for (int i = 1; i < 10; i++)
            {
                BackgroundWorker worker = new BackgroundWorker();
                worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
                worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted);
                worker.RunWorkerAsync(i);

                while (worker.IsBusy == true)
                {
                   Thread.Sleep(100);
                }
            }

Worker_DoWork возвращает datarow, а Worker_RunWorkerCompleted добавляет возвращенный результат в таблицу данных. но функция никогда не достигает в Worker_RunWorkerCompleted в правильном порядке. Как я могу решить это?

EDIT:

Чтобы было понятно, я обновляюсь более подробно.

 <my:DataGrid x:Name="theGrid" RowHeight="30" ItemsSource="{Binding Category}" AutoGenerateColumns="True" HeadersVisibility="All" Margin="235,96.5,84,65.5">
            <my:DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <Expander>
                        <my:DataGrid Height="300" ItemsSource="{Binding Products}" AutoGenerateColumns="True" HeadersVisibility="Column"> </my:DataGrid>
                    </Expander>
                </DataTemplate>
            </my:DataGrid.RowDetailsTemplate>
        </my:DataGrid>


    //List of objects
    List<Category> Categories = new List<Category>();

    private void button1_Click(object sender, RoutedEventArgs e)
    {      
        for (int i = 1; i < 10; i++)
        {
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted);
            worker.RunWorkerAsync(i);

            while (worker.IsBusy == true)
            {
                Thread.Sleep(100);
            }
        }
    }

    void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        long i = Convert.ToInt64(e.Argument);
        Category cat = new Category { CategoryID = i, Name = "Category" + i };
        cat.Products = new List<Product>();

        for (long j = 1; j < 10; j++)
        {
            Product p = new Product { ProductID = (i * j), Name = "Product " + (i * j).ToString() };
            cat.Products.Add(p);
        }

        e.Result = cat;
    }

    void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Category cat = ((Category)e.Result);
        Categories.Add(cat);
        theGrid.ItemsSource = Categories;
    }
}

public class Product
{
    public long ProductID { get; set; }
    public string Name { get; set; }
}

public class Category
{
    public long CategoryID { get; set; }
    public string Name { get; set; }
    public List<Product> Products { get; set; }
}

Ответы [ 2 ]

4 голосов
/ 10 января 2012

Вы по-прежнему блокируете поток пользовательского интерфейса - он не сможет обрабатывать события, пока все ваши BackgroundWorkers не завершат работу.Это противоречит целой точке из BackgroundWorker.Вы должны начать их, и просто дать им закончить.Если вам нужно внести какие-то другие изменения после их завершения, вы должны сделать это в обработчике для RunWorkerCompleted - возможно, сохраняя счетчик того, сколько из них закончилось (если вы запускаете их параллельно), или запускать новое, если хотитезапускать их последовательно, пока вы не запустите все те, которые хотите запустить.

1 голос
/ 10 января 2012

При использовании фонового работника главная цель - избежать блокировки / зависания потока пользовательского интерфейса.Если метод Do_Work занимает много времени, попробуйте создать событие Progress_Changed в фоновом режиме и обновите прогресс в пользовательском интерфейсе с помощью этого метода.Worker_Completed вызывается только после завершения связанной задачи фонового работника.Вам нужно вызвать событие Progress Changed между Do_Work для обновления прогресса.

Некоторый код для связанного события Progress Changed:

worker.WorkerReportsProgress = true;
worker.ProgressChanged += new ProgressChangedEventHandler(Worker_ProgressChanged); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...