2

就这么简单!这是我的一个尝试,它要求与它线程化的函数在可暂停部分中通过自身使用 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();
        }
    }
}

可悲的是,它不是可以随时暂停的线程,而是需要等待外部处理才能继续的函数的线程。就像游戏暴徒的动作一样,它需要绘制循环才能继续绘制它的帧,并且暴徒的 AI 在游戏的主循环中处理。

我想它会使它成为某种伪线程?反正。

它将允许暴徒在每个循环中一点一点地处理这个动作,而不是像在它的 AI 中进行级联检查......

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 暂停的)是按值而不是引用传递的 - 我该如何解决它?

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


这是代码的一个版本,一个原型说:

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

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

4

1 回答 1

1

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

这是最后的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 对象,但它也可以作为参数传递给函数。

是的,它是以佛教地狱命名的!

于 2012-11-25T21:50:45.820 回答