2016-03-30 21 views
4

C# ile çoklu iş parçacığı programlamada yeniyim. Benim sorunum, bir sonraki satıra devam etmeden önce bitirmek için başka bir iş parçacığında çalıştırılan bir yöntemi nasıl beklemem gerektiğini bilmem. Örneğin, buBaşka bir iş parçacığı üzerinde işlem yapmak için nasıl bir yöntem beklemeli?

public class A 
{  
    int i; 

    public A() 
    { 
     i = 0; 
    } 

    protected void RunLoop() 
    { 
     while(i < 100) 
     { 
      i++; 
     } 
    } 

    public void Start() 
    { 
     TimerResolution.TimeBeginPeriod(1); 
     runThread = new Thread(new ThreadStart(RunLoop)); 
     running = true; 
     runThread.Start(); 
    } 
} 

public class B 
{ 
    A classAInstance = new A(); 
    A.Start(); 
    Console.Writeline(i); 
} 

gibi bir şey Şu anda, (yani i = 100) Benim istediğim bu değil ki, konsolda 0 yazdırır. Bunu yapmanın en iyi yolu nedir? BTW, class A

teşekkür oluşturulur runThread erişimi yok.

DÜZENLEME:

Çok daha kodlarını değiştirmeden bu sorunu çözmek için biraz zordu. Bu nedenle, public void Start()'da bir koşul ekleyerek, RunLoop'un ayrı bir iş parçacığı içinde çalıştırılıp çalıştırılmayacağına karar verebildik. Durum, Enum alanı kullanılarak tanımlandı. Yardım için

public void Start() 
{ 
    TimerResolution.TimeBeginPeriod(1); 
    running = true; 
    if (runningMode == RunningMode.Asynchronous) 
    { 
     runThread = new Thread(new ThreadStart(RunLoop)); 
     runThread.Start(); 
    } 
    else 
    { 
     RunLoop(); 
    } 
} 

Ve

public enum RunningMode { Asynchronous, Synchronous }; 

teşekkürler herkese.

+3

, muhtemelen diğer iş parçacığı üzerinde neler olup bittiğini tespit edemez:

Kodunuz bu basit olabilir. İş parçacığı örneğine erişiminiz varsa, 'Thread.Join' kullanarak bitirmesini bekleyebilirsiniz, ancak buna sahip değilseniz, sorun çözülemez. Senkronizasyon işbirliği gerektirir. –

+0

Tesadüfen, kodunuz 'A.i' ye erişimimiz olmadığı için derlenemez (ve eğer yaparsak, iş parçacığı güvenli olmaz). Öyleyse, iş parçanız devleti paylaşıyor mu, yapmıyor mu? Senin gerçek * problemin nedir ve neden açık bir iş parçacığı gerektirdiğini düşünüyorsun? –

+0

* İş parçacığı kullanma * yerine, görev bittiğinde bazı eylemleri gerçekleştirmek için Görevler ve 'bekletme ',' Devam Et', Bekle() 'vb. Tanımladığınız senaryonun basitleştirilmesi için yaratılmışlardır (en azından) –

cevap

0

"Lock" işleci ile birlikte Monitor.Wait() ve Monitor.Pulse() kullanmayı seviyorum. Çalışıyor, ama bu tekniği kullandığınızda dikkatli olmalısınız. Göstermek için kodunuzda bazı değişiklikler ekledim. Aşağıdaki kod, istediğiniz gibi i == 100 basıyor.

public class A 
{ 
    int i; 

    public object SyncObject 
    { get; private set; } 

    public A() 
    { 
     SyncObject = new object(); 
     i = 0; 
    } 

    protected void RunLoop() 
    { 
     while (i < 100) 
     { 
      i++; 
     } 

     lock (SyncObject) 
     { 
      Monitor.Pulse(SyncObject); 
     } 
    } 

    public void Start() 
    { 
     var runThread = new Thread(new ThreadStart(RunLoop)); 
     runThread.Start(); 
    } 

    public void PrintI() 
    { 
     Console.WriteLine("I == " + i); 
    } 
} 

public class B 
{ 
    public static void Run() 
    { 
     A classAInstance = new A(); 
     lock (classAInstance.SyncObject) 
     { 
      classAInstance.Start(); 
      Monitor.Wait(classAInstance.SyncObject); 
     } 
     classAInstance.PrintI(); 
    } 
} 
2

tercih edilen bir yöntem Task Parallel Library (TPL) kullanın ve await ile Task kullanmaktır.

İplikleri kullanmanız gerekiyorsa, bir yöntem sonlandırmak için ManualResetEvent veya ManualResetEventSlim kullanın.

void Main() 
{ 
    var a = new A(); 
    a.Start(); 
    a.FinishedEvent.WaitOne(); 
    Console.WriteLine(a.Index); 
} 

// Define other methods and classes here 
public class A 
{ 
    ManualResetEvent mre = new ManualResetEvent(false); 
    int i; 

    public EventWaitHandle FinishedEvent 
    { 
     get { return mre; } 
    } 

    public int Index 
    { 
     get { return i; } 
    } 

    public A() 
    { 
     i = 0; 
    } 

    protected void RunLoop() 
    { 
     while (i < 1000) 
     { 
      i++; 
     } 
     mre.Set(); 
    } 

    public void Start() 
    { 
     var runThread = new Thread(new ThreadStart(RunLoop)); 
     runThread.Start(); 
    } 
} 
2

Hayatınız görevler ile çok daha iyi olurdu. Diğer koduna hiçbir erişiminiz varsa

var task = Task.Factory.StartNew(() => 
{ 
    var i = 0; 
    while (i < 100) 
    { 
     i++; 
    } 
    return i; 
}); 

Console.WriteLine(task.Result); 
+0

Bir 'task.Wait()' öğesine ihtiyacınız varsa, OP, işlemin bitmesini nasıl bekleyeceğini sorar – Jcl

+4

@Jcl, 'task.Result',' task.Wait() işleviyle aynı olan engelleme çağrısıdır. –

+0

@KirillShlenskiy ohhh, bu tamamen doğru, benim kötü! – Jcl

İlgili konular