Как вызвать в потоке пользовательского интерфейса компонента WinForm? - PullRequest
0 голосов
/ 25 октября 2010

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

Task myTask = Task.Factory.StartNew (() => SomeMethod(someArgs));
myTask.ContinueWith (antecedant => uiTextBox.Text = antecedant.Exception.Message,
                     TaskContinuationOptions.OnlyOnFaulted);

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

Однако Invoke или BeginInvoke не определены в классе Component.

Как действовать дальше?


ОБНОВЛЕНИЕ

Также обратите внимание, что Invoke / BeginInvoke / InvokeRequired недоступны из моего класса, производного от Component, так как Component их не предоставляет.

Ответы [ 2 ]

3 голосов
/ 26 октября 2010

Вы можете просто добавить свойство к своему компоненту, позволяя клиенту установить ссылку на форму, которую можно использовать для вызова его метода BeginInvoke ().

Это также может быть сделано автоматически, предпочтительно, чтобы никто немогу забытьЭто требует немного волшебства времени проектирования, которое является довольно непроницаемым.Я не придумал это сам, я получил это из компонента ErrorProvider.Надежный источник и все такое.Вставьте это в исходный код вашего компонента:

using System.Windows.Forms;
using System.ComponentModel.Design;
...
    [Browsable(false)]
    public Form ParentForm { get; set; }

    public override ISite Site {
        set {
            // Runs at design time, ensures designer initializes ParentForm
            base.Site = value;
            if (value != null) {
                IDesignerHost service = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
                if (service != null) this.ParentForm = service.RootComponent as Form;
            }
        }
    }

Дизайнер автоматически устанавливает свойство ParentForm, когда пользователь удаляет ваш компонент в форме.Используйте ParentForm.BeginInvoke ().

1 голос
/ 25 октября 2010

Для этого вы можете использовать делегатов.

    delegate void UpdateStatusDelegate (string value);


    void UpdateStatus(string value)
    {
        if (InvokeRequired)
        {
            // We're not in the UI thread, so we need to call BeginInvoke
            BeginInvoke(new UpdateStatusDelegate(UpdateStatus), new object[]{value});
            return;
        }
        // Must be on the UI thread if we've got this far
        statusIndicator.Text = value;
    }
...