在.NET中有类似于Qt :: QueuedConnection的东西吗?

时间:2010-10-27 20:13:09

标签: c# .net multithreading qt thread-safety

在Qt中,每个对象associated with a thread都有一个很好的习惯用法,所以它的所有事件处理程序都会only run in that thread(当然,除非直接调用)。

在C#/ .NET中有没有类似的东西?如果没有,你会如何开始自己编写?

示例:

// threaded.h
#include <QThread>
#include <QDebug>
#include <QtGlobal>

class ThreadedObject : public QObject {
    Q_OBJECT
public:
    ThreadedObject(const QString &name){
        Name = name;
        // the default QThread implementation is an empty event loop
        Thread = new QThread(this);
        moveToThread(Thread);
        Thread->start();
    }

public slots:
    void tick() {
        qDebug() << Name << "in thread" << (int)QThread::currentThreadId();
    }

private:
    QThread *Thread;
    QString Name;
};

// main.cpp
#include <QtCore/QCoreApplication>
#include <QTimer>
#include "threaded.h"


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    ThreadedObject *foo = new ThreadedObject("Foo");
    QTimer footimer;
    QObject::connect(&footimer, SIGNAL(timeout()), foo, SLOT(tick()));

    ThreadedObject *bar = new ThreadedObject("Bar");
    QTimer bartimer;
    QObject::connect(&bartimer, SIGNAL(timeout()), bar, SLOT(tick()));

    qDebug() << "Main thread is" << (int)QThread::currentThreadId();

    footimer.start(1300);
    bartimer.start(3240);

    return a.exec();
}

将输出:

Main thread is 3916 
"Foo" in thread 3824 
"Foo" in thread 3824 
"Bar" in thread 3920 
"Foo" in thread 3824 
...

2 个答案:

答案 0 :(得分:3)

在.NET中与此最接近的类比可能是SynchronizationContext

例如,这由Task Parallel Library用于将连续编组返回到UI线程。

但是,没有一个可在任何线程上运行的内置实现。在.NET 4中使用BlockingCollection<T>编写一个相当容易,但它不包含在Framework中。它也有些不同,因为它不会自动将事件编组回到该线程上 - 它更像是一个构建块,它提供了此类操作所需的功能。

答案 1 :(得分:0)

WPF Dispatcher!

using System;
using System.Windows.Threading;
using System.Threading;

namespace dispatchertest
{
    public class Dispatched : DispatcherObject
    {
        readonly object Lock = new object();
        readonly string _name;
        public string Name { get { return _name; } }

        public Dispatched(string name) {
            this._name = name;
        }

        public void tick(object sender, EventArgs e) {
            lock ( Lock ) {
                Console.WriteLine("{0} in thread {1}", Name, Thread.CurrentThread.ManagedThreadId);
            }
        }
    }

    class Program
    {
        static void Main(string[] args) {

            var timer = new DispatcherTimer(DispatcherPriority.Send, Dispatcher.CurrentDispatcher);

            Thread thread1 = new Thread(() => {
                var d2 = Dispatcher.CurrentDispatcher;
                var foo = new Dispatched("Foo");


                var timer1 = new DispatcherTimer(DispatcherPriority.Send, Dispatcher.CurrentDispatcher);
                timer1.Interval = new TimeSpan(0,0,0,0, milliseconds: 809);
                timer1.Tick += foo.tick;


                timer1.Start();
                Dispatcher.Run();
            });

            var bar = new Dispatched("Bar");
            timer.Tick += bar.tick;

            thread1.Start();

            timer.Interval = new TimeSpan(0,0,0,0, milliseconds: 1234);
            timer.Start();
            Dispatcher.Run();
        }
    }
}

输出:

Foo in thread 10
Bar in thread 9
Foo in thread 10
Foo in thread 10
Bar in thread 9
Foo in thread 10
Bar in thread 9
Foo in thread 10
Foo in thread 10
Bar in thread 9
Foo in thread 10
Bar in thread 9
Foo in thread 10
Foo in thread 10