.NET 中是否有类似于 Qt::QueuedConnection 的东西?

发布于 2024-09-29 01:13:52 字数 1738 浏览 1 评论 0原文

在 Qt 中,有一个很好的习惯用法,即让每个对象与一个线程关联,以便其所有事件处理程序将 仅在该线程中运行(当然,除非直接调用)。

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 
...

In Qt, there is a nice idiom to have each object associated with a thread, so that all its event handlers will only run in that thread (unless called directly, of course).

Is there anything even remotely like that in C#/.NET? If not, how would you start writing your own?

Example:

// 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;
};

and

// 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();
}

will output:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

故乡的云 2024-10-06 01:13:52

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

例如,任务并行库使用它来将连续编组回 UI 线程。

然而,没有一个可以在任何线程上工作的内置实现。在 .NET 4 中使用 BlockingCollection 编写一个相当容易,但它不包含在框架中。它还有些不同,因为它不会自动为您将事件封送回该线程 - 它更像是一个构建块,提供此类操作所需的功能。

The closest analogy to this in .NET would likely be SynchronizationContext.

This is used, for example, by the Task Parallel Library for marshalling continations back to a UI thread.

There isn't, however, a built-in implementation that works on any thread. It's fairly easy to write one using BlockingCollection<T> in .NET 4, but it isn't included in the Framework. It also is somewhat different, in that it doesn't automatically marshal the events back onto that thread for you - it's more of a building block that provides the functionality required for this type of operation.

神妖 2024-10-06 01:13:52

WPF 调度程序!

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

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();
        }
    }
}

Output:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文