c# - 实现一个可暂停的线程类

标签 c# multithreading

就这么简单!这是我的一次尝试,它要求与它线程化的函数在可暂停部分中通过自身使用 Pause() 函数。

using System;
using System.Threading;

class BlackThread {
    private bool paused;
    private Thread innerThr;

    // ---

    public bool IsAlive {
        get {
            return innerThr.IsAlive;
        }
    }

    // ===

    public void SetAndGo (ThreadStart start) {
        paused = false;

        innerThr = new Thread(start);
        innerThr.Start();
        WaitForIt();
    }

    // ---

    public void Pause() {
        paused = true;
        while (paused);
    }

    public void Unpause() {
        paused = false;
    }

    public void WaitForIt() {
        while(!paused && IsAlive);
    }

    public void Continue() {
        Unpause();
        WaitForIt();
    }
}

class MainClass {
    static void pausableFunction (BlackThread self) {
        Console.WriteLine("* Waiting...");
        self.Pause();
        Console.WriteLine("* Doing stuff.");
        self.Pause();
        Console.WriteLine("* Finished!");
    }

    static void Main() {
        BlackThread noir = new BlackThread();
        noir.SetAndGo(() => pausableFunction(noir));

        while (noir.IsAlive) {
            Console.Write("> ");
            Console.ReadKey();
            noir.Continue();
        }
    }
}

遗憾的是,它不是一个可以随时暂停的线程,而是一个线程,用于需要等待外部处理才能继续的函数。就像游戏生物的 Action 一样,需要在继续之前由绘制循环绘制其框架,并且生物的 A.I. 在游戏的主循环中处理。

我猜它会变成某种伪线程?无论如何。

这将允许生物在每个循环中一点一点地处理这个 Action ,而不是在其 A.I. 中进行级联检查。喜欢...

if mob is doing action {
    if mob has already done this previous part of the action {
        do the following part
    }
}

...它宁愿是这样的,在一个线程中:

do the first step of the action
Wait for it to be rendered...
do the following step of the action
Wait for it to be rendered...
do the last step of the action
(Action ends here, no need to wait for anything anymore)

现在,我的实现有一个错误,我不知道如何修复。当它应该取消暂停 BlackThread 时,它在使用它的函数(在本例中为 pausableFunction())中保持暂停状态。我想这是因为实例是如何传递的?

如果这就是我的猜测 - 也就是说,某些东西(我猜它是 bool paused)是按值而不是引用传递的 - 我该如何解决它?

我真的很习惯 C 和 C++ 的指针,所以在处理 C# 中对象值在作用域之间的通信时,有时我会有点纠结。


这是工作代码的一个版本,一个原型(prototype)说:

using System;
using System.Threading;

class Program {
    static bool paused;

    static void Pause() {
        paused = true;
        while (paused);
    }

    static void Unpause() {
        paused = false;
    }

    static void WaitForIt(Thread waited) {
        while(!paused && waited.IsAlive);
    }

    static void Continue (Thread ToStop) {
        Unpause();
        WaitForIt(ToStop);
    }

    static void SetAndGo (out Thread thread, ThreadStart Start) {
        thread = new Thread(Start);
        thread.Start();
        WaitForIt(thread);
    }

    // ---

    static void thr (string chant) {
        // Console.WriteLine("Waiting...");
        // Pause();
        // Console.WriteLine("{0}", chant);
        // Pause();
        // Console.WriteLine("Well, I'm finished!");

        Console.WriteLine("I'm finished!");
    }

    static void Main() {
        // Thread tt = new Thread(() => thr());
        // tt.Start();
        // WaitForIt(tt);

        Thread tt;
        SetAndGo(out tt, (() => thr("I'm doing stuff.")));

        while (tt.IsAlive) {
            Console.Write("> ");
            Console.ReadKey();
            Continue(tt);
        }
    }
}

我之所以不使用它,只是因为我宁愿让所有事情都由一个特定的类负责,这也会提高可读性。

最佳答案

好吧,我已经完成了我已经尝试过的事情,所以我会把我的代码留在这里以供将来引用!

最后就是BlackThread类:

using System;
using System.Threading;

class BlackThread { 
    //* ===== *//

    private AutoResetEvent pauser = new AutoResetEvent(false);
    private AutoResetEvent waiter = new AutoResetEvent(false);

    private Thread innerThr;

    // ----- //

    public bool IsActing {
        get {
            if (innerThr != null) return innerThr.IsAlive;
            else return false;
        }
    }

    //* ===== *//

    public void KickStart_(ThreadStart start) {
        innerThr = new Thread(start);
        innerThr.Start();

        WaitForIt();
    }

    // ----- //

    // FOR THE THREADED FUNCTION
    public void Wait() {
        waiter.Set();
        pauser.WaitOne();
    }

    public void End() {
        waiter.Set();
    }

    // ----- //

    // FOR BLACKTHREAD MANAGING
    private void WaitForIt() {
        waiter.WaitOne();
    }

    public void Continue() {
        if (IsActing) {
            pauser.Set();
            WaitForIt();
        }
    }

    //* ===== *//
}

这里是它的使用示例:

class MainClass {
    static void pausableFunction() {
        Console.WriteLine("* Waiting...");

        Event.Wait();

        Console.WriteLine("* Doing stuff.");
        Thread.Sleep(1000);

        Event.Wait();

        Console.WriteLine("* Finished!");

        Event.End();
    }

    static void anotherFunction(int foo) {
        Console.WriteLine("* Wanna know the value of a number?");

        Event.Wait();

        Console.WriteLine("* I'll tell you. It's {0}!", foo);

        Event.End();
    }

    static void simpleFunction() {
        Console.WriteLine("* I'm done already!");
    }

    static BlackThread Event = new BlackThread();   
    static Random Rand = new Random();

    static void Main() {        
        int r;

        do {
            if (!Event.IsActing) {
                Console.WriteLine();
                r = Rand.Next(3);

                if (r == 0) {
                    Event.KickStart_(() => pausableFunction());
                }
                else if (r == 1) {
                    simpleFunction();
                }
                else {
                    Event.KickStart_(() => anotherFunction(Rand.Next(20) + 1));
                }
            }
            else {
                Event.Continue();
            }

            Console.Write("> ");
            Console.ReadKey();
        } while(true);
    }
}

我最后选择使用的是两个 AutoResetEvent 处理程序。一个在需要暂停的线程的函数中管理,暂停主循环,等待者 ARE,另一个暂停器 ARE,在主循环中管理,并暂停具有支持 BlackThread 的函数的线程;也就是说,可以访问 BlackThread 实例。

在本例中,我使用了静态 BlackThread 对象,但它也可以作为参数传递给函数。

是的,它是以佛教 hell 命名的!

关于c# - 实现一个可暂停的线程类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13547890/

相关文章:

c# - 优化用于导入的 Entity Framework 查询

c# - ASP.NET - IE8 中控件位置的问题

java - Android 与标准 java 上的不同行为

c# - IIS 7 上的 nHibernate,SQLClientPermissionException

c# - 将 DirectShow 视频窗口附加到 WPF 控件

java - 多处理kafka消息

java - java中的同步和同步块(synchronized block)

java - 如果我停止正在运行的 java 项目,ExecutorService 会发生什么情况

java - Akka 如何从 ForkJoinPool 中获益?

C# Windows Phone 8.1 语言选择