[C#] Вызов события из потока

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by GlooK, 9 Jan 2011.

  1. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Есть класс:
    Code:
    namespace LiveInternet
    {
        public class CategoryEventArgs : EventArgs
        {
            public string listCategory { get; private set; }
            public CategoryEventArgs(string listCategory)
            {
                this.listCategory = listCategory;
            }
        }
        
        [COLOR=Green]// Объявление делегата для события[/COLOR]
        public delegate void CategoryEventHandler(object sender, CategoryEventArgs e);
        public event CategoryEventHandler CategoryReceived;
    
            public void GetCategory()
            {
                [COLOR=Green]// Запуск потока[/COLOR]
                Thread catThread = new Thread(new ThreadStart(ThGetCategory));
                catThread.Start();
            }
    
            private void ThGetCategory()
            {
                [COLOR=Green]// Вызов события из потока[/COLOR]
                ...
                ...
    [B]            if (CategoryReceived != null)
                {
                    CategoryReceived(this, new CategoryEventArgs(_listCategory));
                }[/B]
                ...
                ...
            }
    
    Класс используется следующим образом:
    Code:
    ...
    ...
    using LiveInternet;
    
    namespace LiveRating
    {
        public partial class frmLiveRating : Form
        {
            Rating liveRating = new Rating();
    
            private void frmLiveRating_Load(object sender, EventArgs e)
            {
                [COLOR=Green]// Подписываемся на событие[/COLOR]
                liveRating.CategoryReceived += new Rating.CategoryEventHandler(liveRating_CategoryReceived);
                [COLOR=Green]// Вызываем метод класса, он запускает поток[/COLOR]
                liveRating.GetCategory();
            }
    
            [COLOR=Green]// Произошло событие[/COLOR]
            void liveRating_CategoryReceived(object sender, CategoryEventArgs e)
            {
                [COLOR=Green]// Обращение к визуальному объекту[/COLOR]
                comboCategory.Items.Clear(); 
                [COLOR=Green][B]// Вызывает ошибку: Cross-thread operation not valid: Control 'comboCategory' accessed from a thread other than the thread it was created on.[/B][/COLOR]
            }
        }
    }
    
    Вылетает ошибка:
    Cross-thread operation not valid: Control 'comboCategory' accessed from a thread other than the thread it was created on.

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

    Вопрос:
    Как вызвать, именно вызвать, потокобезопасное событие?
     
  2. cheater_man

    cheater_man Member

    Joined:
    13 Nov 2009
    Messages:
    651
    Likes Received:
    44
    Reputations:
    7
    попробуй через делегаты
     
  3. Irdis

    Irdis Elder - Старейшина

    Joined:
    6 Feb 2006
    Messages:
    248
    Likes Received:
    52
    Reputations:
    3
    Code:
    void liveRating_CategoryReceived(object sender, CategoryEventArgs e)
    {
           if (InvokeRequired)
          {
            CategoryEventHandler eventDelegate = liveRating_CategoryReceived;
            Invoke(eventDelegate, sender, e);
          }
         else
         {
               //UI thread
         }
    }
    
    Или BeginInvoke