Длительная операция - обновление пользовательского интерфейса с помощью BitmapImage не работает - PullRequest
1 голос
/ 04 марта 2012

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

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

private delegate void SimpleDelegate2(BitmapImage bi);
private delegate void SimpleDelegate(string st1, string st2);

private void Process(string st1)
{
    try
    {
        string st2 = "test st2";
        SimpleDelegate del = new SimpleDelegate(LongRunningProcess);
        del.BeginInvoke(st1, st2, null, null);
    }
    catch
    {
        //do some failsafe thing
    }
}

private void LongRunningProcess(string st1, string st2)
{
    //do some long processing with the strings
    BitmapImage bi = new BitmapImage();//there will be an actual bitmap here

    SimpleDelegate2 del1 = delegate(BitmapImage bimg)
    {
        ImageControlOnWPFform.Source = bimg; //null;
    };
    this.Dispatcher.BeginInvoke(DispatcherPriority.Send, del1, bi);
}

Проблема в том, чтоЯ не могу установить значение Source элемента управления изображением на bimg , но могу установить значение null! Всякий раз, когда я пытаюсь установить значение bimg, я получаю исключение, которое говорит вызывающий поток не может получить доступ к этому объекту, поскольку он принадлежит другому потоку .Я также попытался установить его непосредственно на bi, что также дает то же исключение.

Но я могу без проблем установить источник на null, что означает, что я могу изменить значение SourceКонтроль изображения.Но как мне получить доступ к bi или bimg?Я что-то не так делаю?

Также: Я заметил, что приведенные аргументы последнего BeginInvoke не соответствуют какой-либо перегрузке метода , но они по-прежнемупринят как действительный и работает должным образом.Когда я указываю на BeginInvoke, мне показывают совершенно другой набор перегрузок методов, чем те, которые появляются, когда я набираю ( после имени метода.Почему?

1 Ответ

2 голосов
/ 04 марта 2012

Ответ на главный вопрос

Выполните bi.Freeze() перед использованием BitmapImage в потоке пользовательского интерфейса. Операция Freeze сделает BitmapImage доступным только для чтения и поточно-ориентированным.

    ...
    //do some long processing with the strings
    BitmapImage bi = new BitmapImage();//there will be an actual bitmap here
    bi.Freeze();

    SimpleDelegate2 del1 = delegate(BitmapImage bimg)
    ...

Ответ за Также

Класс System.Windows.Threading.Dispatcher имеет пять подписей для метода BeginInvoke:

public DispatcherOperation BeginInvoke(Delegate method, params object[] args);
public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method);
public DispatcherOperation BeginInvoke(Delegate method, DispatcherPriority priority, params object[] args);
public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method, object arg);
public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method, object arg, params object[] args);

Однако три подписи (с подписью DispatcherPriority priority в качестве первого аргумента) имеют следующие теги:

[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]

Именно поэтому они не отображаются при наборе ( после имени метода.

...