【问题标题】:Unity multithreading producer consumerunity多线程生产者消费者
【发布时间】:2017-03-24 14:15:26
【问题描述】:

我创建了一个生产者类将字符串添加到控制器类中的队列的情况。控制器类通知工作类有工作并执行工作,在这种情况下将字符串附加到文件中。我无法完成这项工作。该文件已创建,但没有附加任何内容。我在成功的Java中创造了这种情况。我会把这段代码放在最后。只是为了澄清我需要在 C# 中解决这个问题。

通过使用调试器,我得出的结论是线程在进入等待后不会唤醒。不过我可能是错的。

注意:我不想使用协程

生产者方法:

void Start () {
    for (int i = 0; i < 100; i++)
    {
        Ccontroller.Instance.AddWork("no: " + i);
    }   
}

控制器类 对于锁定,我尝试了 Monitor.enter/exit 和当前解决方案。为了简单起见,我更改了实现。此实现使用工作人员静态队列。线程需要静态队列。

public class Ccontroller : Singleton<Ccontroller>
{
public Queue<string> workLoad = new Queue<string>();
public Worker worker;

public Object lockGetWork = new Object();

public void AddWork(string toProcess)
{
    Worker.workload.Enqueue(toProcess);

    lock (lockGetWork)
    {
        Monitor.PulseAll(lockGetWork);
    }
}

public string GetWork()
{
    string process;

    process = workLoad.Dequeue();

    return process;
}
}

工人阶级: 公共类工人:MonoBehaviour {

static string path = @"d:\test.txt";
Thread t;

public static Queue<string> workload = new Queue<string>();

private void Awake()
{
    t = new Thread(Work);
}

// Use this for initialization
void Start()
{
    //create file
    if (!File.Exists(path))
    {
        using (StreamWriter sw = File.CreateText(path)) { }
    }
    t.Start();
}

static void Work()
{

while (true)
{
    if (workload.Peek() != null)
        {
            using (StreamWriter sw = File.AppendText(path))
            {
                sw.WriteLine(workload.Dequeue());
            }
        }
        else
        {
            Monitor.Wait(Ccontroller.Instance.lockGetWork);
        }
    }
}
}

Java 代码中的代码和所需的情况: 生产者类中的方法:

public void StartWork(){
    for(int i=0; i<200; i++){

        controller.AddWork("work order: "+i);
    }
}

控制器:

public class WorkController {

private Queue<String> workload = new ArrayDeque<String>();
private AtomicInteger LockAdd = new AtomicInteger();
private AtomicInteger LockRemove = new AtomicInteger();

public void AddWork(String work){
        workload.add(work);
        synchronized(LockAdd){
            LockAdd.notify();
        }       
}

public String RemoveWork(){
    String work;
    synchronized(LockRemove){
        work= workload.remove();
    }
    return work;
}  
}

工人:

public class Worker {

public WorkController controller;

Thread work = new Thread(){
    public void run(){
        while(true){
            try{
                System.out.println(controller.RemoveWork());
            }catch(NoSuchElementException ex){
                 System.out.println("no work");
                try {
                    wait();
                } catch (InterruptedException ex1) {
                    Logger.getLogger(Worker.class.getName()).log(Level.SEVERE, null, ex1);
                }
            }
        }
    }
};

void StartWorker(){
    work.start();
}

}

【问题讨论】:

  • Unity 不是线程安全的......但是如果你正在做一些不涉及统一代码的事情,你不妨把它做成一个单独的过程

标签: c# multithreading unity3d locking producer-consumer


【解决方案1】:

什么解决了这个问题:似乎在 Unity 和/或 c# 中,您可以在同一对象的 Lock 语句中执行 Monitor.wait。

【讨论】:

    猜你喜欢
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多