Вызов события из отдельного потока
От: TDLite http://tdlite.ru
Дата: 09.01.11 08:04
Оценка:
Есть класс:
namespace LiveInternet
{
    public class CategoryEventArgs : EventArgs
    {
        public string listCategory { get; private set; }
        public CategoryEventArgs(string listCategory)
        {
            this.listCategory = listCategory;
        }
    }
    
    // Объявление делегата для события
    public delegate void CategoryEventHandler(object sender, CategoryEventArgs e);
    public event CategoryEventHandler CategoryReceived;

        public void GetCategory()
        {
            // Запуск потока
            Thread catThread = new Thread(new ThreadStart(ThGetCategory));
            catThread.Start();
        }

        private void ThGetCategory()
        {
            // Вызов события из потока
            ...
            ...
            if (CategoryReceived != null)
            {
                CategoryReceived(this, new CategoryEventArgs(_listCategory));
            }
            ...
            ...
        }

Класс используется следующим образом:
...
...
using LiveInternet;

namespace LiveRating
{
    public partial class frmLiveRating : Form
    {
        Rating liveRating = new Rating();

        private void frmLiveRating_Load(object sender, EventArgs e)
        {
            // Подписываемся на событие[/COLOR]
            liveRating.CategoryReceived += new Rating.CategoryEventHandler(liveRating_CategoryReceived);
            // Вызываем метод класса, он запускает поток
            liveRating.GetCategory();
        }

        [COLOR=Green]// Произошло событие[/COLOR]
        void liveRating_CategoryReceived(object sender, CategoryEventArgs e)
        {
            // Обращение к визуальному объекту
            comboCategory.Items.Clear(); 
            // Вызывает ошибку: Cross-thread operation not valid: Control 'comboCategory' accessed from a thread other than the thread it was created on.
        }
    }
}

Вылетает ошибка:
Cross-thread operation not valid: Control 'comboCategory' accessed from a thread other than the thread it was created on.

Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно.
Много гугли, находил схожие вопросы, но ответов на них не было.

Вопрос:
Как вызвать, именно вызвать, потокобезопасное событие?
Уютный бложикhttp://tdlite.ru
события потоки
Re: Вызов события из отдельного потока
От: Lloyd Россия  
Дата: 09.01.11 08:14
Оценка:
Здравствуйте, TDLite, Вы писали:

TDL>Вылетает ошибка:

TDL>Cross-thread operation not valid: Control 'comboCategory' accessed from a thread other than the thread it was created on.

TDL>Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно.


Что в этом неправильного?
Re: Вызов события из отдельного потока
От: SE Украина  
Дата: 09.01.11 08:15
Оценка:
Здравствуйте, TDLite, Вы писали:

TDL>Вылетает ошибка:

TDL>Cross-thread operation not valid: Control 'comboCategory' accessed from a thread other than the thread it was created on.

TDL>Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно.

TDL>Много гугли, находил схожие вопросы, но ответов на них не было.

TDL>Вопрос:

TDL>Как вызвать, именно вызвать, потокобезопасное событие?

Используй метод базового класса Control.Invoke для переключения в поток, в котором был создан контрол.
Re: Вызов события из отдельного потока
От: HowardLovekraft  
Дата: 09.01.11 08:16
Оценка:
Здравствуйте, TDLite, Вы писали:

Почему не
public event EventHandler<CategoryEventArgs> CategoryReceived;

вместо
public delegate void CategoryEventHandler(object sender, CategoryEventArgs e);
public event CategoryEventHandler CategoryReceived;

?
TDL>Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно.
Почему? Как именно было бы правильно?
Re[2]: Вызов события из отдельного потока
От: TDLite http://tdlite.ru
Дата: 09.01.11 08:20
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>Здравствуйте, TDLite, Вы писали:


HL>Почему не

HL>
HL>public event EventHandler<CategoryEventArgs> CategoryReceived;
HL>

HL>вместо
HL>
HL>public delegate void CategoryEventHandler(object sender, CategoryEventArgs e);
HL>public event CategoryEventHandler CategoryReceived;
HL>

HL>?
TDL>>Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно.
HL>Почему? Как именно было бы правильно?

Кхм... я только недавно начал изучать c#.
Просто хотелось, чтобы конечный пользователь мог использовать класс без каких-либо дополнительных изворотов.
т.е. если использовать Invoke, то внутри класса. Пробовал вызывать событие из синхронизированного места (lock), но не помогло.
Уютный бложикhttp://tdlite.ru
Re[3]: Вызов события из отдельного потока
От: TDLite http://tdlite.ru
Дата: 09.01.11 08:53
Оценка:
Вот нашел темку http://rsdn.ru/forum/dotnet.gui/3019102.aspx
Автор: MozgC
Дата: 11.07.08

Второй способ, как раз по мне. Попробуй сделать как описано там, но все равно буду рад другим решениям.
Уютный бложикhttp://tdlite.ru
Re[3]: Вызов события из отдельного потока
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.01.11 08:57
Оценка:
Здравствуйте, TDLite, Вы писали:

TDL>>>Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно.

HL>>Почему? Как именно было бы правильно?

TDL>Кхм... я только недавно начал изучать c#.

TDL>Просто хотелось, чтобы конечный пользователь мог использовать класс без каких-либо дополнительных изворотов.
Без изворотов в общем случае с асинхронными методами не получится работать.

TDL>т.е. если использовать Invoke, то внутри класса. Пробовал вызывать событие из синхронизированного места (lock), но не помогло.

Не всегда конечный пользователь вызывает работает с окном, потому работать с Control.Invoke или нет, будет решать именно конечный пользователь.

Здесь перечислены основные асинхронные паттерны, используемые в дотнете.
Re[3]: Вызов события из отдельного потока
От: HowardLovekraft  
Дата: 09.01.11 09:00
Оценка:
Здравствуйте, TDLite, Вы писали:

TDL>Просто хотелось, чтобы конечный пользователь мог использовать класс без каких-либо дополнительных изворотов.

WinForms (и WPF, и наверняка еще что-то) не thread-safe.
Если бы вы писали свой GUI framework, как бы обеспечивалась синхронизация доступа к состоянию элемента управления?
Re[4]: Вызов события из отдельного потока
От: TDLite http://tdlite.ru
Дата: 09.01.11 09:16
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, TDLite, Вы писали:


TDL>>>>Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно.

HL>>>Почему? Как именно было бы правильно?

TDL>>Кхм... я только недавно начал изучать c#.

TDL>>Просто хотелось, чтобы конечный пользователь мог использовать класс без каких-либо дополнительных изворотов.
S>Без изворотов в общем случае с асинхронными методами не получится работать.

TDL>>т.е. если использовать Invoke, то внутри класса. Пробовал вызывать событие из синхронизированного места (lock), но не помогло.

S>Не всегда конечный пользователь вызывает работает с окном, потому работать с Control.Invoke или нет, будет решать именно конечный пользователь.

S>Здесь перечислены основные асинхронные паттерны, используемые в дотнете.

Спасибо, обязательно прочитаю.
В общем такая ситуация нормальна, когда сам пользователь должен обеспечить потокобезопасность события?
Если так, то брыкаться не буду. Просто хочу "правильно" программировать.
Уютный бложикhttp://tdlite.ru
Re[5]: Вызов события из отдельного потока
От: samius Япония http://sams-tricks.blogspot.com
Дата: 09.01.11 09:51
Оценка: 3 (1) +1
Здравствуйте, TDLite, Вы писали:

TDL>Здравствуйте, samius, Вы писали:


S>>Не всегда конечный пользователь вызывает работает с окном, потому работать с Control.Invoke или нет, будет решать именно конечный пользователь.


S>>Здесь перечислены основные асинхронные паттерны, используемые в дотнете.

TDL>Спасибо, обязательно прочитаю.
TDL>В общем такая ситуация нормальна, когда сам пользователь должен обеспечить потокобезопасность события?
Да, т.к. только пользователь знает как именно в его случае обеспечить синхронизацию, и нужно ли это делать.

TDL>Если так, то брыкаться не буду. Просто хочу "правильно" программировать.

Тогда лучше сначала почитать о принятых паттернах.

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