Вызов события из оригинальной темы? - PullRequest
3 голосов
/ 08 апреля 2010

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

Вот пример кода для лучшего понимания:

class MyClass
{
    // Original object
    private OriginalObject myObject;

    // My event
    public delegate void StatsUpdatedDelegate(object sender, StatsArgs args);
    public event StatsUpdatedDelegate StatsUpdated;

    public MyClass()
    {
        // Original object event
        myObject.DoSomeWork();
        myObject.AnEvent += new EventHandler(myObject_AnEvent);
    }

    // This event is called on another thread while myObject is doing his work
    private void myObject_AnEvent(object sender, EventArgs e)
    {
        // Throw my custom event here
        StatsArgs args = new StatsArgs(..........);
        StatsUpdated(this, args);
    }
}

Поэтому, когда в моей форме Windows я вызываю, попробуйте обновитьЭлемент управления из события StatsUpdated Я получаю исключение кросс-потока, потому что оно было вызвано в другом потоке.

Что я хочу сделать, это сгенерировать свое пользовательское событие в исходном потоке класса, чтобы в нем мог использоваться элемент управления.

Кто-нибудь может мне помочь?

Ответы [ 3 ]

4 голосов
/ 08 апреля 2010

Вы можете взглянуть на шаблон InvokeRequired / Invoke .

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

Control ctrlToBeModified = // 
if (ctrlToBeModified.InvokeRequired)
{
    Action<Control> del = (Control c) => 
    { 
        // update the control here
    };
    ctrlToBeModified.Invoke(del, ctrlToBeModified);
}

UPDATE:

private void myObject_AnEvent(object sender, EventArgs e)
{
    // Throw my custom event here
    StatsArgs args = new StatsArgs(..........);
    Control control = // get reference to some control maybe the form or 'this'
    if (control.InvokeRequired)
    {
        Action<Control> del = (Control c) => 
        { 
            // This will invoke the StatsUpdated event on the main GUI thread
            // and allow it to update the controls
            StatsUpdated(this, args);
        };
        control.Invoke(del);
    }
}
0 голосов
/ 08 апреля 2010

Похоже, вам нужно изучить классы SynchronizationContext или AsyncOperation.

http://www.codeproject.com/KB/cpp/SyncContextTutorial.aspx

0 голосов
/ 08 апреля 2010

Я не уверен, что это так, но если это безопасно, вы можете добавить в конструктор формы:

Control.CheckForIllegalCrossThreadCalls= false;

Это «легкий путь», который применяется только в некоторых ограниченных сценариях. В моем случае работает как шарм.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...