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, но это как-то неправильно.
Много гугли, находил схожие вопросы, но ответов на них не было.
Вопрос:
Как вызвать, именно вызвать, потокобезопасное событие?
Здравствуйте, 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, но это как-то неправильно.
Здравствуйте, 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 для переключения в поток, в котором был создан контрол.
public event EventHandler<CategoryEventArgs> CategoryReceived;
вместо
public delegate void CategoryEventHandler(object sender, CategoryEventArgs e);
public event CategoryEventHandler CategoryReceived;
? TDL>Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно.
Почему? Как именно было бы правильно?
HL>? TDL>>Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно. HL>Почему? Как именно было бы правильно?
Кхм... я только недавно начал изучать c#.
Просто хотелось, чтобы конечный пользователь мог использовать класс без каких-либо дополнительных изворотов.
т.е. если использовать Invoke, то внутри класса. Пробовал вызывать событие из синхронизированного места (lock), но не помогло.
Здравствуйте, TDLite, Вы писали:
TDL>>>Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно. HL>>Почему? Как именно было бы правильно?
TDL>Кхм... я только недавно начал изучать c#. TDL>Просто хотелось, чтобы конечный пользователь мог использовать класс без каких-либо дополнительных изворотов.
Без изворотов в общем случае с асинхронными методами не получится работать.
TDL>т.е. если использовать Invoke, то внутри класса. Пробовал вызывать событие из синхронизированного места (lock), но не помогло.
Не всегда конечный пользователь вызывает работает с окном, потому работать с Control.Invoke или нет, будет решать именно конечный пользователь.
Здесь перечислены основные асинхронные паттерны, используемые в дотнете.
Здравствуйте, TDLite, Вы писали:
TDL>Просто хотелось, чтобы конечный пользователь мог использовать класс без каких-либо дополнительных изворотов.
WinForms (и WPF, и наверняка еще что-то) не thread-safe.
Если бы вы писали свой GUI framework, как бы обеспечивалась синхронизация доступа к состоянию элемента управления?
Здравствуйте, samius, Вы писали:
S>Здравствуйте, TDLite, Вы писали:
TDL>>>>Есть способ использовать в самом обработчике события (liveRating_CategoryReceived) метод Invoke, но это как-то неправильно. HL>>>Почему? Как именно было бы правильно?
TDL>>Кхм... я только недавно начал изучать c#. TDL>>Просто хотелось, чтобы конечный пользователь мог использовать класс без каких-либо дополнительных изворотов. S>Без изворотов в общем случае с асинхронными методами не получится работать.
TDL>>т.е. если использовать Invoke, то внутри класса. Пробовал вызывать событие из синхронизированного места (lock), но не помогло. S>Не всегда конечный пользователь вызывает работает с окном, потому работать с Control.Invoke или нет, будет решать именно конечный пользователь.
S>Здесь перечислены основные асинхронные паттерны, используемые в дотнете.
Спасибо, обязательно прочитаю.
В общем такая ситуация нормальна, когда сам пользователь должен обеспечить потокобезопасность события?
Если так, то брыкаться не буду. Просто хочу "правильно" программировать.
Здравствуйте, TDLite, Вы писали:
TDL>Здравствуйте, samius, Вы писали:
S>>Не всегда конечный пользователь вызывает работает с окном, потому работать с Control.Invoke или нет, будет решать именно конечный пользователь.
S>>Здесь перечислены основные асинхронные паттерны, используемые в дотнете. TDL>Спасибо, обязательно прочитаю. TDL>В общем такая ситуация нормальна, когда сам пользователь должен обеспечить потокобезопасность события?
Да, т.к. только пользователь знает как именно в его случае обеспечить синхронизацию, и нужно ли это делать.
TDL>Если так, то брыкаться не буду. Просто хочу "правильно" программировать.
Тогда лучше сначала почитать о принятых паттернах.
Кстати, если GetCategory не имеет побочных эффектов, не нуждается в обновлении прогресса или отмене, то лучше вообще не вносить в его реализацию асинхронность.
Пользователь сам вызовет этот метод синхронно или нет по желанию, сам решит, создавать ли для выполнения отдельный поток, вызвать ли метод из потока пула, или воспользоваться BackgroundWorker-ом.