System.Threading.Thread继承

13

是否可以继承Thread类并重写Start方法?


3
为什么你想要这样做?你想达成什么目的? - John Saunders
我敢打赌他只是想将一个或多个强类型参数传递给他的方法。 - Joel Coehoorn
如果他想传递一个单一的强类型参数,他应该查看传递给线程构造函数的ParameterizedThreadStartDelegate。这样他就可以获得一个类型安全的Start重载。 - Yann Schwartz
9个回答

22

为什么有人会想要这样做呢:很多语言(例如Java)和/或线程API(例如Qt)允许开发者通过继承“线程”基类并重载实现线程例程的方法来实现线程。

在Qt中广泛使用这种模型后,我发现它非常方便——整个线程都包含在一个对象内,而不是将线程指向某个函数或方法,这通常会导致奇怪和/或复杂的代码。

这里是使用Qt API的示例代码:

class MyThread : public QThread
{
    Q_OBJECT

protected:
    void run();
};

void MyThread::run()
{
    ...something I need threaded...
}

QThread是Qt的线程基类。要使用MyThread,请创建线程对象的实例并调用QThread :: start()。然后,运行run()的重新实现中的代码将在一个单独的线程中执行。

这个方法的好处是它让你可以将线程所需的所有内容都包含在一个对象中,并且(根据我的经验),它可以形成一个非常连贯的对象模型。我认为它并不能满足每个人的需求,但是说实话,我有点惊讶C#没有这样一个基本的线程模型。

我绝对不相信C#的Thread类因为内核复杂性而被封闭;如果Qt可以提供一个允许继承QThread的跨平台线程库,我认为微软也可以通过在C#中提供类似功能的线程类来实现相同的能力。


4
我同意你的回复,并且我在我的 C++ 代码中也使用了那种抽象类多年。 - Dave
真正的原因是他们想要一个轻量级的封装。:) 没有什么能阻止任何人在官方轻量级封装周围创建更好的封装。 - Liz Av

12
using System.Threading;

namespace NGrubb.Threading {

    public abstract class BaseThread {
        private Thread m_thread;

        public BaseThread() {
            m_thread = new Thread( Run );
        }

        public void Start() {
            m_thread.Start();
        }

        protected abstract void Run();
    }
}

我实际上不会将这样的ThreadBase类放入我的代码库中,但这是一个很好的模板可以使用。谢谢! - HappyNomad

11

不,Thread类是sealed的。这个决定背后的理由是:Thread类是对内核对象的一个棘手且低级别的包装器,所以你不应该去动它。

不过我有一个问题,你为什么想要重写Start方法?你想要实现什么?


同样的问题是为什么有人想要重写Start方法。 - jrista
我敢打赌他只是想将一个或多个强类型参数传递给他的方法。 - Joel Coehoorn

9
我认为任何继承都不能比这更易读的代码:

我认为没有任何一种继承能够产生比这更易读的代码:

Thread myThread = new Thread(() =>
{
    //Do what you want...
});
myThread.Start();

除了Thread是一个密封类,你不能继承Thread。 - Mauricio Gracia Gutierrez
2
如果有足够多的我需要处理和跟踪的奇怪对象在线程内部,那肯定可以。我将编写一个线程,必须动态加载DLL并调用其中的API方法,同时响应来自网络的请求。我需要的不仅仅是线程的方法,还需要一个类。 - skiphoppy

7

不确定为什么您可能想要这样做(即使可以这样做,也不应该这样做),但有一种方法可以规避Thread类被密封的事实-使用扩展方法。更技术性地说,它只是向Start方法组添加一个重载(而不是覆盖),但在您的上下文中仍可能有所帮助。

像这样的东西可能是您想要的:

public static void Start(this Thread thread, int foo)
{
    // Your code here.

    thread.Start();
}

您可以简单地按如下方式调用它:
var thread = new Thread();
thread.Start(123);

5

2

不...

Thread类是一个密封的类,它代表了在操作系统中运行的线程。

[ComVisibleAttribute(true)]
[ClassInterfaceAttribute(ClassInterfaceType.None)]
public sealed class Thread : CriticalFinalizerObject, 
    _Thread

谢谢


2

我也习惯在Java应用程序中使用相同的逻辑,将线程捆绑到对象中,进一步将新进程的启动与其父进程分离是非常有意义的。同样地,很失望C#不支持这种方法。 Dave P


2

这是一个密封类,意味着你无法从它继承。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接