Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Пользовательские сообщения в C#

32K
20 июля 2008 года
ExB
11 / / 28.02.2008
Как из одного потока отправить второму пользовательское сообщение, а во втором потоке это сообщение обработать?
5
21 июля 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: ExB
Как из одного потока отправить второму пользовательское сообщение

Что вы подразумеваете под термином "пользовательское" сообщение?

32K
21 июля 2008 года
ExB
11 / / 28.02.2008
Есть сообщение, которые ОС отправляет приложению, например, WM_MOUSEMOVE или WM_KEYDOWN.
Но насколько я знаю, программист может определить свой тип сообщений и обрабатывать их нужным ему способом, эти сообщения я и имел ввиду, говоря пользовательские сообщения.
5
21 июля 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: ExB
Есть сообщение, которые ОС отправляет приложению, например, WM_MOUSEMOVE или WM_KEYDOWN.
Но насколько я знаю, программист может определить свой тип сообщений и обрабатывать их нужным ему способом, эти сообщения я и имел ввиду, говоря пользовательские сообщения.

А какой смысл использовать столь низкоуровневые операции в столь абстрактной среде как .NET? Операции с сообщениями Windows (System.Windows.Forms.Message) требуются только тогда, когда нужно взаимодействовать с другими (не .NET) оконными приложениями.

32K
21 июля 2008 года
ExB
11 / / 28.02.2008
Каким образом тогда реализуется взаимодействие потоков через сообщения?
5
21 июля 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: ExB
Каким образом тогда реализуется взаимодействие потоков через сообщения?

Вам это нужно для конкретной задачи или интересует чисто теория?
Дело в том, что отправка сообщений потокам не совсем соответствует модели синхронизации потоков, принятой в настоящее время, но в принципе, реализуется достаточно просто: вспомните задачу о синхронизации поставщиков и потребителей с использовнием двух семафоров.

32K
21 июля 2008 года
ExB
11 / / 28.02.2008
Есть конкретная задача.
Есть форма и поток, как из потока изменить свайства, например, label-я. Причем не должно быть больших задержек в работе потока.
241
21 июля 2008 года
Sanila_san
1.6K / / 07.06.2005
Не скажу, что это совсем уж идеальный вариант, но мы делали это через механизм событий. В пределах процесса работает прекрасно.
32K
21 июля 2008 года
ExB
11 / / 28.02.2008
Цитата: Sanila_san
Не скажу, что это совсем уж идеальный вариант, но мы делали это через механизм событий. В пределах процесса работает прекрасно.



А как послать и поймать (обработать) сообщение в .Net?

241
21 июля 2008 года
Sanila_san
1.6K / / 07.06.2005
Все волнующие подробности можно прочитать в МСДН. Там и найдёте то, что вам больше подойдёт.
32K
21 июля 2008 года
ExB
11 / / 28.02.2008
Цитата: Sanila_san
Все волнующие подробности можно прочитать в МСДН. Там и найдёте то, что вам больше подойдёт.



Я уже второй день капаюсь в MSDN и нашел только это
ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/CPref17/html/P_System_Windows_Forms_Message_Msg.htm

Код:
using System;
using System.Drawing;
using System.Windows.Forms;

namespace csTempWindowsApplication1
{
    public class Form1 : System.Windows.Forms.Form
    {
        // Constant value was found in the "windows.h" header file.
        private const int WM_ACTIVATEAPP = 0x001C;
        private bool appActive = true;

        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }
       
        public Form1()
        {
            this.Size = new System.Drawing.Size(300,300);
            this.Text = "Form1";
            this.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            // Paint a string in different styles depending on whether the
            // application is active.
            if (appActive)
            {
                e.Graphics.FillRectangle(SystemBrushes.ActiveCaption,20,20,260,50);
                e.Graphics.DrawString("Application is active", this.Font, SystemBrushes.ActiveCaptionText, 20,20);
            }
            else
            {
                e.Graphics.FillRectangle(SystemBrushes.InactiveCaption,20,20,260,50);
                e.Graphics.DrawString("Application is Inactive", this.Font, SystemBrushes.ActiveCaptionText, 20,20);
            }
        }

    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
        protected override void WndProc(ref Message m)
        {
            // Listen for operating system messages.
            switch (m.Msg)
            {
                // The WM_ACTIVATEAPP message occurs when the application
                // becomes the active application or becomes inactive.
                case WM_ACTIVATEAPP:

                    // The WParam value identifies what is occurring.
                    appActive = (((int)m.WParam != 0));

                    // Invalidate to get new text painted.
                    this.Invalidate();

                    break;                
            }
            base.WndProc(ref m);
        }
    }
}

А как отправить сообщение?
5
21 июля 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: ExB
А как отправить сообщение?


Вот вам делать нечего чем искать "костыли".
This is the Way.

Код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace PropertySetter {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();

            message_queue = new Queue<CrossThreadProcedure>(MAX_MESSAGE_QUEUE_LENGTH);

            writer_sem = new Semaphore(MAX_MESSAGE_QUEUE_LENGTH, MAX_MESSAGE_QUEUE_LENGTH);
            reader_sem = new Semaphore(0, MAX_MESSAGE_QUEUE_LENGTH);
           
            heavy_computing_thread = new Thread(HeavyComputingThread);
            heavy_computing_thread.IsBackground = true;
           
            message_dispatcher_thread = new Thread(MessageDispatcherThread);
            message_dispatcher_thread.IsBackground = true;
           
            heavy_computing_thread.Start();
            message_dispatcher_thread.Start();
        }
       
       
        private const int MAX_MESSAGE_QUEUE_LENGTH = 20;
       
        private Queue<CrossThreadProcedure>    message_queue;    
       
        private Semaphore writer_sem;
       
        private Semaphore reader_sem;
       
        private Thread heavy_computing_thread;            
       
        private Thread message_dispatcher_thread;

        private void Enqueue(CrossThreadProcedure proc) {
            writer_sem.WaitOne();
            lock(message_queue) {
                message_queue.Enqueue(proc);
            }
            reader_sem.Release();
        }

        private CrossThreadProcedure Dequeue() {
            CrossThreadProcedure next_proc;
            reader_sem.WaitOne();
            lock(message_queue) {
                next_proc = message_queue.Dequeue();
            }
            writer_sem.Release();
            return next_proc;
        }

        private void HeavyComputingThread() {
            int i = 0;
            while(true) {                
                ++i;
                //  "отправляем" сообщение на обработку
                Enqueue(new CrossThreadProcedure(new ThreadStart(delegate {
                    // формируем код "собщения" для выполнения в потоке интерфейса
                    this.Text = i.ToString();
                })));
            }
        }
       
        private void MessageDispatcherThread() {
            while(true) {
                Thread.Sleep(100);
                //   получаем следующее сообщение из очереди
                CrossThreadProcedure next_proc = Dequeue();
                //   выполняем его код в потоке интерфейса
                this.Invoke(next_proc.Method, next_proc.Args);
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
            heavy_computing_thread.Abort();
            message_dispatcher_thread.Abort();
           
            heavy_computing_thread.Join();
            message_dispatcher_thread.Join();            
        }

    }
   
   
    public sealed class CrossThreadProcedure {
        public CrossThreadProcedure(Delegate proc, params object[] args) {
            this._proc = proc;
            this._args = args;
        }
       
        private readonly Delegate _proc;
        public Delegate Method { get { return _proc; } }
       
        private readonly object[] _args;        
        public object[] Args { get { return _args; } }
           
    }
   
}

Идя алгоритма. Имеем 2 потока и одну очередь сообщений. Один поток выполняет какието особо важную и нетерпящую отлогательств задачу, другой же занимается тем, что слушает, чего периодически посылает тот первый поток, и выполняет синхронизацию с потком интерфейса для отображения инфы. Очередь сообщений имеет некоторую максимальную длину - MAX_MESSAGE_QUEUE_LENGTH, это позволяет "не отвлекаться" основному потоку от выполняемых действий.
Механизм работы с очередью - классичский алгоритм на двух семафорах.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог