Таймер C # для вызовов STAThread COM в консольном приложении - PullRequest
0 голосов
/ 23 августа 2011

У меня есть консольное приложение, которое должно запустить метод, использующий COM.Программа начинается с [STAThread].Программа выполняется правильно, когда не используется процесс таймера, но, по-видимому, страдает от блокировки обратно на консоль при использовании таймера.

Я использовал System.Threading.Timer и System.Timers.Timer и не работал ни один.В настоящее время я добавил поток, вызывающий метод (Transmit ()), который использует COM.Если я очищаю основной поток с помощью Console.Readline, программа возобновляет работу с того места, где был заблокирован COM-объект, но, конечно, программа закрывается, и я теряю нужные функции таймера.

Я не мог понять, какустановите SynchronizingObject для получения обратного вызова ISynchronizeInvoke при использовании консольного приложения.

Я не ищу несколько потоков, мне просто нужно, чтобы метод Transmit вызывался через регулярный интервал и работал с COM, возвращая результаты обратно вконсоль.

class Program
{
    private static System.Timers.Timer transTimer;

    [STAThread]
    static void Main(string[] args)

       {
                transTimer = new System.Timers.Timer();
                transTimer.Enabled = true;
                transTimer.Interval = 6000;
                transTimer.Elapsed += new System.Timers.ElapsedEventHandler(transTimer_Elapsed);
                transTimer.Start();
                Console.ReadLine();
                transTimer.Dispose();
                return;
            }


    static void transTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (transTimer.Enabled)
        {
            transTimer.Enabled = false;
            Thread thread = new Thread(Transmit);
            thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
            thread.Start();
            thread.Join(); //Wait for the thread to end
            transTimer.Enabled = true;
        }
    }

Ответы [ 2 ]

2 голосов
/ 23 августа 2011

Вы нарушаете важное требование однопоточной квартиры (STA), оно должно прокачать цикл сообщений.Без него COM не может перенаправить вызов из рабочего потока в поток, создавший компонент COM.Это необходимо для обеспечения того, чтобы компонент использовался в поточно-ориентированном режиме.Проблема не в том, что вы использовали таймер, а в том, что вы использовали поток.Наблюдаемый эффект состоит в том, что вызов блокируется.

Получить цикл сообщений в консольном приложении сложно.Одним из обходных путей является не создание COM-компонента в вашем методе Main (), а рабочий поток, чтобы он не создавался.Реализуйте вызовы периода, вызывая Sleep () в цикле.

Другой обходной путь - , а не , используя атрибут [STAThread].Затем COM автоматически создаст поток STA, чтобы обеспечить COM-компонент безопасным домом.Этот поток также прокачивает цикл сообщений.Каждый звонок теперь будет маршалированным, избегайте, если вы сделаете их много.

0 голосов
/ 23 августа 2011

.NET способ настроить насос сообщений - Application.Run (). Вызовите его из отдельного выделенного потока и используйте перегрузку, которая не принимает форму. Сохраняйте свой код COM в этом потоке, а код консоли - в главном потоке, и у вас не должно быть проблем с консолью, блокирующей вашу логику COM. Если вам нужен таймер для взаимодействия с логикой COM, используйте объект System.Windows.Forms.Timer, созданный запущенным в потоке COM. Таким образом, обратные вызовы / события от него также будут выполняться в потоке COM.

...