Пользовательский интерфейс не отвечает при загрузке большого документа в потоке пользовательского интерфейса, даже если реализован BackgroundWorker - PullRequest
1 голос
/ 19 января 2010

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

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

Я пытаюсь использовать для этого Backgroundworker. Код, который я пробую, имеет следующую форму:

public class MyForm: Form
{
private delegate bool OpenFile(string filePath);
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{



    OpenFile oF = new OpenFile(document.Open);
    var openFile = this.Invoke(oF, MyFileName);  

    e.Result = openFile;
}
}

Теперь в потоке пользовательского интерфейса, которому принадлежит document, когда он выполняет операцию Open, должно появиться диалоговое окно с обновлением, а основной поток должен оставаться отзывчивым все равно могу перетащить форму в любом случае мне нравится). Это то, чего я пытался достичь.

Проблема в том, что приведенный выше код приведет к зависанию обоих моих потоков (основного потока пользовательского интерфейса и потока диалогового окна) во время загрузки. У меня вопрос, есть ли способ решить эту проблему?

P / S: я пробовал var openFile = Invoke(oF, MyFileName) и var openFile = BeginInvoke(oF, MyFileName) и var openFile = OtherControl.Invoke(oF, MyFileName), все не помогло.

Ответы [ 2 ]

2 голосов
/ 19 января 2010

Приведенный вами пример не показывает достаточно, чтобы четко определить проблему. Я предполагаю, что ваш класс не содержит явный метод Invoke(), поэтому ваш пример вызывает Form.Invoke(). Если это так, то вы неправильно понимаете цель этого метода.

Form.Invoke() обеспечивает выполнение включенного делегата в потоке пользовательского интерфейса . Поэтому ваш фоновый поток на самом деле не выполняет работу, вместо этого ваш фоновый поток возвращается к вашему потоку пользовательского интерфейса до выполнения делегата ... отсюда и неотзывчивый пользовательский интерфейс.

Возможно, вы стали жертвой неудачной двусмысленности ... и System.Delegate, и System.Windows.Forms.Form & Control содержат методы с именами Invoke() и BeginInvoke(), но служат различным целям. К сожалению, здесь ваш образец немного неполон. Является ли OpenFile делегатом? Содержит ли ваш класс явный метод Invoke()?


Обновление: после некоторого обсуждения в комментариях возможные варианты были сокращены до:

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

  • Использование .NET Reflector для проверки внутреннего / непубличного API элемента управления и попытки использовать Reflection для переопределения текущего поведения путем вызова непубличных методов или установки полей / свойств

0 голосов
/ 22 декабря 2010

Более старый вопрос, но ни один ответ не помечен как правильный, поэтому я полагаю, что проблема не была решена текущими ответами.

У меня была проблема с теми же симптомами.При использовании фонового рабочего потока пользовательский интерфейс стал неотвечающим.

Я в основном следовал следующим учебникам: http://msdn.microsoft.com/en-us/library/hybbz6ke.aspx http://broadcast.oreilly.com/2010/06/understanding-c-using-backgrou.html

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

Надеюсь, это поможет.

...