BackgroundWorkers никогда не прекращают быть занятыми

for (do it a bunch of times)
{         
    while (backgroundWorker1.IsBusy && backgroundWorker2.IsBusy &&
           backgroundWorker3.IsBusy && backgroundWorker4.IsBusy &&
           backgroundWorker5.IsBusy)
    {
        System.Threading.Thread.Sleep(0001);
    }

    if (!backgroundWorker1.IsBusy)
    {
        backgroundWorker1.RunWorkerAsync();
    }
    else if (!backgroundWorker2.IsBusy)
    {
        backgroundWorker2.RunWorkerAsync();
    }
    else if (!backgroundWorker3.IsBusy)
    {
        backgroundWorker3.RunWorkerAsync();
    }
    else if (!backgroundWorker4.IsBusy)
    {
        backgroundWorker4.RunWorkerAsync();
    }
    else if (!backgroundWorker5.IsBusy)
    {
        backgroundWorker5.RunWorkerAsync();
    }
}

это работает пять раз (каждый BG-рабочий однажды) и застревает в в то время как. backgroundworkers никогда не прекращают быть занятыми? как я проверяю наличие?

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

- [отредактируйте запрос]---

На самом деле это был только фиктивный параметр, я удалил его и забыл выводить его, я только использую его для вызова dowork, кто делает грязное задание:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    timeconsumingfunction(publicstring);
}

И timeconsumingfunction ДЕЙСТВИТЕЛЬНО заканчивается. ступая в него в отладчик и рабочую строку на строку, он идет до конца и прибывает в финал '}'. Это означает, что заканчивается, правильно?

---[ОТРЕДАКТИРУЙТЕ ОТВЕТ]----работавший, ПРОСТО заменив строку

System.Threading.Thread.Sleep(0001);

с

Application.DoEvents();

Я предполагаю, что это выполнило бы фон, но не получило бы ответ и не обновило бы теги IsBusy.

Спасибо все, большие ответы, помогли много!

9
задан Olivier Jacot-Descombes 27 June 2014 в 15:26
поделиться

7 ответов

Ваш цикл вызывает взаимную блокировку, BGW не может завершиться. Проблема в событии RunWorkerCompleted, оно возникает в потоке пользовательского интерфейса. Этот бит магии BGW требует, чтобы поток пользовательского интерфейса был в режиме ожидания, он должен перекачивать свой цикл сообщений. Проблема в том, что поток пользовательского интерфейса не простаивает и не перекачивает сообщения, он застрял в цикле for. Таким образом, обработчик событий не может работать, и IsBusy остается верным.

Вам нужно будет сделать это по-другому. Воспользуйтесь событием RunWorkerCompleted для запуска кода, который вы обычно запускаете после этого цикла for. Не поддавайтесь искушению вызвать Application.DoEvents () внутри цикла.

34
ответ дан 4 December 2019 в 06:19
поделиться

Предлагаю вам изменить код для обработки события RunWorkerCompleted, чтобы получать уведомления о том, когда ваши BackgroundWorkers закончат свою работу. Пример использования BackgroundWorker приведен в официальной документации .

3
ответ дан 4 December 2019 в 06:19
поделиться

Запишите необработанные байты, полученные по URL-адресу /sdcard/tmp.jpg , и просмотрите их на компьютере.

Изображения JPEG сжимаются в 8x8 (или 16x16) плитках. «Пикселизация», как вы описываете, на самом деле находится в этих плитках, предполагая, что «плохое» изображение является JPEG, который более агрессивно сжат, чем другой.

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

-121--2858850-

Петля вызывает взаимоблокировку, BGW не могут быть завершены. Проблема в событии RunWorureCompleted, оно возникает в потоке пользовательского интерфейса. Этот бит магии BGW требует, чтобы поток пользовательского интерфейса был свободен, он должен прокачивать свой цикл сообщений. Проблема в том, что поток пользовательского интерфейса не простаивает и не перекачивает сообщения, он застрял в цикле for. Таким образом, обработчик событий не может выполняться, и IsBusy остается истинным.

Вам нужно будет сделать это по-другому. Используйте событие RunWorireCompleted для запуска кода, который обычно запускается после этого цикла. Сопротивляйтесь искушению вызвать Приложение .DoEvents () внутри цикла.

-121--3525853-

Основной поток должен перекачивать сообщения Windows (либо вызывать Application.DoEvents в цикле while, либо использовать Systems.Windows.Forms.Timer вместо цикла).

Если не откачивать сообщения Windows, «завершенные» уведомления работника системы OM не будут обрабатываться, поэтому состояние останется занятым.

1
ответ дан 4 December 2019 в 06:19
поделиться

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

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

2
ответ дан 4 December 2019 в 06:19
поделиться

Посмотрите на следующие статьи:

-121--3770443-

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

Но если кто-то хочет иметь фантазию одного конструктора и все еще иметь различные реализации, мы можем подумать о передаче объекта, производного от какого-то интерфейса, в качестве входных данных конструктору и, возможно, проверить тип входных данных для создания экземпляра. Это своего рода абстрактная фабрика в данном случае.

В одном месте мы имеем класс, подобный следующему:

using System;

namespace MyApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            base1 t1 = new type1();
            class1 c1 = new class1(t1);
            base1 t2 = new type2();
            class1 c2 = new class1(t2);
            //.....
        }
    }

    public class class1
    {
        public class1(base1 mytype)
        {
           switch(mytype.type)
               case mytype.types.type1
                   return createObjectOftype1();
               case mytype.types.type2
                   return createObjectOftype2();
               case mytype.types.type3
                   return createObjectOftype3();
        }

        public class1 createObjectOftype1()
        {
            //....
        }

        public class1 createObjectOftype2()
        {
           //...
        }

        public class1 createObjectOftype2()
        {
           //...
        }

    }


    public class base1
    {
        publlic Enum Types {0 "type1",.... 
    }

    public class type1:base1
    {
        //.....
    }

    public class type2:base1
    {
        //.....
    }
}
-121--4536246-

.IsBusy указывает только на то, что фоновый работник фактически выполняет операцию. Он будет занят до тех пор, пока «что-то» не будет завершено. Кажется, что «что-то» не заканчивает, держа своих фоновиков занятыми.

Так что было бы полезно, если бы вы могли объяснить, что такое «что-то», и, возможно, сколько времени нужно, чтобы выполнить «что-то» на основном потоке.

0
ответ дан 4 December 2019 в 06:19
поделиться

Проблема в том, что все, что вы делаете в worker.RunWorkerAsync () , никогда не завершается. Возможно, в вашем событии DoWork есть какой-то бесконечный цикл или что-то подобное.

Вот рабочий пример, который выбирает следующего свободного рабочего:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        private static List<MyWorker> _Workers;

        static void Main(string[] args)
        {
            _Workers = new List<MyWorker>();

            for (int i = 0; i < 5; i++)
            {
                _Workers.Add(CreateDefaultWorker(i));
            }

            StartJobs(20000);
            Console.ReadKey();
        }

        private static void StartJobs(int runtime)
        {
            Random rand = new Random();
            DateTime startTime = DateTime.Now;

            while (DateTime.Now - startTime < TimeSpan.FromMilliseconds(runtime))
            {
                var freeWorker = GetFreeWorker();

                if (freeWorker != null)
                {
                    freeWorker.Worker.RunWorkerAsync(new Action(() => DoSomething(freeWorker.Index, rand.Next(500, 2000))));
                }
                else
                {
                    Console.WriteLine("No free worker available!");
                    Console.WriteLine("Waiting for free one...");
                    WaitForFreeOne();
                }
            }
        }

        private static MyWorker GetFreeWorker()
        {
            foreach (var worker in _Workers)
            {
                if (!worker.Worker.IsBusy)
                    return worker;
            }

            return null;
        }

        private static void WaitForFreeOne()
        {
            while (true)
            {
                foreach (var worker in _Workers)
                {
                    if (!worker.Worker.IsBusy)
                        return;
                }
                Thread.Sleep(1);
            }
        }

        private static MyWorker CreateDefaultWorker(int index)
        {
            var worker = new MyWorker(index);

            worker.Worker.DoWork += (sender, e) => ((Action)e.Argument).Invoke();
            worker.Worker.RunWorkerCompleted += (sender, e) => Console.WriteLine("Job finished in worker " + worker.Index);

            return worker;
        }

        static void DoSomething(int index, int timeout)
        {
            Console.WriteLine("Worker {1} starts to work for {0} ms", timeout, index);
            Thread.Sleep(timeout);
        }
    }

    public class MyWorker
    {
        public int Index { get; private set; }
        public BackgroundWorker Worker { get; private set; }

        public MyWorker(int index)
        {
            Index = index;
            Worker = new BackgroundWorker();
        }
    }
}
0
ответ дан 4 December 2019 в 06:19
поделиться

У меня была аналогичная проблема, и для ее решения я заключил основную функцию с помощью try ... catch ... и, наконец ... заявление.

1
ответ дан 4 December 2019 в 06:19
поделиться