实现可循环的线程类

时间:2012-11-25 03:01:06

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

可悲的是,它不是任何时候都可以暂停的,而是需要等待外部处理能够继续的功能的线程。就像游戏怪物的动作一样,它需要画面循环才能画画循环才能继续播放,并且游戏的A.I.是在游戏的主循环中处理的。

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

它允许暴徒在每个循环中逐位处理此动作,而不是在其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暂停)是通过值而不是引用来传递的 - 我该如何修复它?

我真的习惯了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);
        }
    }
}

我只是没有使用它,因为我宁愿让所有东西负责特定课程,这也会提高可读性。

1 个答案:

答案 0 :(得分: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对象,但它也可以作为参数传递给函数。

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