2017-03-24 4 views
0

Ich erstellte eine Situation, in der eine Producer-Klasse Zeichenfolgen zu einer Warteschlange in einer Controller-Klasse hinzufügt. Die Controller-Klasse benachrichtigt die Worker-Klasse darüber, dass Arbeit vorhanden ist und führt die Arbeit aus. In diesem Fall werden Strings an eine Datei angehängt. Ich kann diese Arbeit nicht bekommen. Die Datei wird erstellt, es wird jedoch nichts angehängt. Ich habe diese Situation in Java geschaffen, wo ich erfolgreich war. Ich werde diesen Code am Ende setzen. Nur um zu klären muss ich das in C# lösen.Unity Multithreading Producer Consumer

Mit der Verwendung des Debuggers kam ich zu dem Schluss, dass der Thread nach dem Warten nicht aufwacht. Ich könnte mich jedoch irren.

Als Anmerkung: Ich möchte nicht Koroutinen Methode

Producer verwenden:

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

Controller-Klasse Zum Verriegeln habe ich versucht, Monitor.Enter/Ausgang und aktuelle Lösung. Ich änderte die Implementierung abit für die Leichtigkeit. Diese Implementierung verwendet die statische Workerwarteschlange. Die statische Warteschlange wurde für den Thread benötigt.

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

Arbeiterklasse: public class Worker: 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); 
     } 
    } 
} 
} 

-Code in Java-Code und die gewünschte Situation: Methode der Erzeugerklasse:

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

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

Der Controller:

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

Der Arbeiter:

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

} 
+1

Einheit ist nicht threadsicher ... Aber wenn Sie etwas tun, das den Einheitscode nicht berührt, können Sie es auch einfach zu einem separaten Prozess machen –

Antwort

0

Was das Problem gelöst: Es scheint, dass in der Einheit und/oder C# Sie Monitor.Wait innerhalb einer Lock-Anweisung des gleichen Objekts zu tun.

Verwandte Themen