2016-03-22 18 views
0

Bu soru iki bölümden oluşmaktadır. Birkaç sunucudan bilgi alan ve bu bilgiyi bir DB'ye kaydeden bir konsol uygulamasına sahibim. Bunu enabel olarak yürütmek için simültane olarak kullanıyorum. Bu yürütmeyi her dakika otomatik yapmaya çalışıyorum. ben bu işe yarayabilir bulundu stackoverflow aranıyorHer dakika doğru olarak iş parçacığı nasıl yürütülür?

:

var timer = new System.Threading.Timer((e) => 
     { 
      var models = ServerHandler.GetServerModels(); 

      foreach (var m in models) 
      { 
       ServerHandler.MakeThreads(m); 
      } 

      Console.WriteLine("Running..."); 
      Console.WriteLine("Press 'X' to exit or close the window, i : " + i); 

      i++; 


     }, null, 0, TimeSpan.FromMinutes(1).Seconds); 

Ancak bu tahmin gibi çalışmıyor, sadece bir defa çalıştırır.

TimeSpan.FromMinutes(0.5).Seconds 

Veya: i Örneğin bunun için geçerseniz

TimeSpan.FromSeconds(30).Seconds 

Sonra çalışır. Neyi yanlış yapıyorum? Bu sorunun

İkinci kısım:

bu aslında bir şeye yukarıda gösterdiği gibi başka olur çalışmaktadır. Süreç sürekli olarak çalışıyor ve 474 iş parçacığının ardından çöküyor ve sistemin bellek yetersiz olduğunu söylüyor.

Bunun için iş parçacığı uyku kullanmayı denedim, ancak bunu yaptığımda, bir kez çalıştırıldıktan sonra yürütmeyi durdurur.

public static void MakeThreads(ServerModel model) 
{ 
    Thread thread = new Thread(() => SaveServerInfo(model)); 
    thread.Start(); 
    //Thread.Sleep(1); 
    //thread.Join(); 

} 

nasıl bu iş yapabilirsiniz: Bu da yardımcı olabilir eğer dahil

?

+2

'TimeSpan.FromMinutes (1) .Seconds' döner Sen 60. –

+0

I döndürür 'TimeSpan.FromMinutes (1) .TotalSeconds' istiyor 0. TimeSpan aşırı yüklenmesini kullanırdı. _https: //msdn.microsoft.com/en-us/library/ah1h85ch (v = vs.110) .aspx_ –

+0

Nasıl? TimeSpan.FromSeconds (60) .Seconds? –

cevap

2

.Seconds kullanılarak ilk sorununuzda yalnızca saniye değerini döndürür, ancak dakika değerini .5 olarak tanımlarsınız, bu nedenle saniye her zaman sıfır olacaktır.

Eğer

TimeSpan.FromMinutes(0.5).TotalSeconds 

ve size milisaniye tanımlamak gerekiyor kullandığınız zaman içinde totalseconds

kullanmaya gerek saniye dönmek isterseniz. Yani çok sayıda iş parçacığı alıyorsunuz çünkü her 300 milyon milisaniye yerine 30 milisaniye çalışıyor.

Yani ben her zaman daha kolaydır

(int)(1000 * 60 * 0.5) // Then you just replace the 0.5 with the number of seconds. 
+0

bunu denedi, 475 iş parçacığı olana kadar her saniyede çalışır ve sonra – ThunD3eR

+0

çöküyor Bu nedenle yürütme aralığın daha uzun sürüyor. Bu bir performans problemi. Başka bir şey denemelisin ... –

+0

@ Ra3IDeN Güncellediğim cevabın ikinci bölümüne bak. – CathalMF

1

Temelde bir zamanlayıcı tam olarak ne yapacağını gerekiyordu gelmez bulmak

TimeSpan.FromMinutes(0.5).TotalMilliseconds 

ya da ne kullanın: Her 0.5 saniyede bir kod çalıştırmasına. sizin durumunuzda :) An, bu ... bir sorun

Kişisel sorun gibi görünüyor

Uzun çözeltisi (sözdizimi hataları vb, ben not defteri bu yazıyorum kontrol edin) Konularınızı kontrol etmediğiniz.İşte bunu çözmek bütçeyi nasıl: (Bu uzun bir çözüm gösterir nasıl daha fazla veya daha az çalışır)

while (true) 
{  
    // we want to run it again in 0.5 seconds. 
    DateTime start = DateTime.UtcNow.AddSeconds(0.5); 

    Thread[] threads = new Thread[models.Count]; 
    for (int i=0; i<models.Count; ++i) 
    { 
     threads[i] = new Thread((a) => SaveServerInfo((ServerModel)a)); 
     threads[i].Start(models[i]); 
    } 

    for (int i=0; i<models.Count; ++i) 
    { 
     threads[i].Join(); 
    } 

    DateTime current = DateTime.UtcNow; 
    if (current < start) 
    { 
     Thread.Sleep(start.Subtract(current)); 
    } 

} 

Kısa çözüm Ancak

, bu da size sorunları verebilir: Çok sayıda yumurtlamaya olabilir İş Parçacığı. Bu, iplik havuzu adı verilen bir mekanizma ile çözülebilir. Sonradan anlaşıldı ki, bu çözmek için basit bir yolu vardır:

static void DoStuff(string s) 
{ 
    // change to a value > 0.5 as well to ensure everything works 
    Thread.Sleep(TimeSpan.FromSeconds(0.1)); 
    Console.WriteLine(s); 
} 

static void Handle(List<string> models) 
{ 
    while (true) 
    { 
     // we want to run it again in 0.5 seconds. 
     DateTime start = DateTime.UtcNow.AddSeconds(0.5); 

     Parallel.ForEach(models, (a) => DoStuff(a)); 
     DateTime current = DateTime.UtcNow; 
     if (current < start) 
     { 
      Thread.Sleep(start.Subtract(current)); 
     } 
    } 
} 

static void Main(string[] args) 
{ 
    List<string> models = new List<string>(); 
    for (int i = 0; i < 10; ++i) 
    { 
     models.Add(i.ToString()); 
    } 

    Handle(models); 

} 
+0

bu işe yaramadı. İlk katliam, hata ayıklayıcısında çalıştırmamış olduğumda aralık dışı bir istisna oluşturdu. İkinci çözüm sadece konuları bir kez çalıştırıp durdu. – ThunD3eR

+0

@ Ra3IDeN İlk örnekte bir iş parçacığı başladığını unuttum; Bu şimdi düzeltildi. İkinci çözüm olduğu gibi çalışır. Aralık dışı istisna dışı bir endeks alırsanız, koleksiyonu bir iş parçacığında değiştirirsiniz. ** Bu hiçbir durumda izin verilmez, bir yarış durumu yaratırsınız! ** İşe yaramayacağını iddia ettiğiniz gibi En az bir test vakası oluşturdum ve gayet iyi çalışıyor; Kendinizi kontrol etmek için çekinmeyin. – atlaste

İlgili konular