Multi Thread Progralama Hakkında - C#
-
collectData isminde içerisinde HTTP requesti atarak bilgi toplayan ve bu çektiği bilgileri veritabanına kaydeden bir methodum var. Bu methodun içerisinde 2 tane while döngüsü'de mevcut. Ancak recursive bir method değil, gelen http response'una göre yeni request atıyor filan falan.
Yapmak istediğim collectData methodunu multi thread olarak çalıştırmak. Bazen while döngüleri çok uzun sürebiliyor. Böyle olduğunda işlemin tamamlanması çok zaman alıyor. Multi thread olarak methodu çalıştırıp zamandan tasarruf sağlamak istiyorum.
collectData methodunu aşağıdaki şekilde çalıştırıyorum
Task[] tasks = new Task[8]
{
Task.Factory.StartNew(() => { collectData ();}),
Task.Factory.StartNew(() => { collectData ();}),
Task.Factory.StartNew(() => { collectData ();}),
Task.Factory.StartNew(() => { collectData ();}),
Task.Factory.StartNew(() => { collectData ();}),
Task.Factory.StartNew(() => { collectData ();}),
Task.Factory.StartNew(() => { collectData ();}),
Task.Factory.StartNew(() => { collectData ();})
};
Task.WaitAll(tasks);
Bu şekilde çağırmama rağmen methodlar senkron olarak çalışıyor. Bunları asenkron olarak nasıl çağırıp hepsinin tamamlanmasını bekleyebilirim acaba?
*İhtiyacımda Asenkron-Multithread karmaşasındada kalmadım değil, zaten yazıdanda terimin yerlerindeki hataları fark edersiniz.
-
iki sene önce paralel programalama dersinde c# bilmememe rağmen TPL kütüphanesini iyi kavradıydım.
Şimdi pararleliği en mükemmel sağlayabilmemiz için (yani tavsiye için) paralel çalıştırman gereken fonksiyonun içeriğini bilmemiz gerek.
Ama sana söyleyeceğim asıl tavsiye. While döngüsünün bulunduğu collectdata() fonsiyonunu pararlel çalıştırmak için;
While döngüsünün paralelleştirmeye çalış...
-
DrKill bunu yazdı
iki sene önce paralel programalama dersinde c# bilmememe rağmen TPL kütüphanesini iyi kavradıydım.
Şimdi pararleliği en mükemmel sağlayabilmemiz için (yani tavsiye için) paralel çalıştırman gereken fonksiyonun içeriğini bilmemiz gerek.
Ama sana söyleyeceğim asıl tavsiye. While döngüsünün bulunduğu collectdata() fonsiyonunu pararlel çalıştırmak için;
While döngüsünün paralelleştirmeye çalış...
While'i paralleştirmem biraz zor güzüküyor çünkü while'da linear bir işlem var. A'nın sonucu B'ye, B'nin sonucu C'ye lazım. En son gelen değer null olduğunda while bitiyor.
-
Peki hocamda birşey soracam gönderdiğin kodlarda hata yok mu?
Task[] tasks = new Task[8]
tasks[1].Factory.StartNew(() => {
tasks[2].Factory.StartNew(() => {
şeklinde olmayacak mı? Paralel atama yapmamışsın ki hocam. Sıralı yaptırıyorsun zaten kodlara göre.
Ayrıca 8 tane tasks oluşturma, 8 tane paralel task çalılşacağı anlamına gelmez. İşlemcin mantıksal kaçtane thread destekliyorsa en fazla o kadar prarlel çalışabilirsin. Daha fazlası gerçek manada paralel olmaz. Sadece sanal olarak (simüle edilmiş gibi düşün) paralel olur. Yani biri durur diğeri başlar şeklinde.
DrKill tarafından 02/May/15 17:03 tarihinde düzenlenmiştir -
hocam asenkron metodlar için task completion source u kullanabilirsin.. wait kullanmak bazı durumlarda tehlikeli olabiliyor
daha önce yazdığım bir kod parçasına bakabilirsin örnek olarak
Edit: Alttaki kodlar düzgün kopyalanmıyor, kod düzenleyicide sorun var. Buradan bakabilirsiniz koda
public Task GetAvailableLibraries(string serverName) { var tcs = new TaskCompletionSource(); service.GetAvailableLibrariesCompleted += (sender, args) => { if (args.Error != null) tcs.TrySetResult(new List()); try { if (args.Result != null) tcs.TrySetResult(args.Result.ToList()); else tcs.TrySetResult(new List()); } catch { tcs.TrySetResult(new List()); } }; try { service.GetAvailableLibrariesAsync(serverName); } catch (Exception ex) { } return tcs.Task; }bunu da şu şekilde çağırıyorum
var result = await Task.Run(() => helper.GetAvailableLibraries(serverUrl));
burdaki result un türü List dir. Eğer fonksiyonda bir hata oluşmuşsa liste boş gelecektir. Tabi istersen null dönderebilirsin, sana kalmış.. Eğer sunucu işleriyle uğraşmıyorsan kesin sonuç döneceksen tcs.SetResult 'ı kullanabilirsin.
Not: await keywordünü kullandığım için, içinde bulunduğu fonksiyon async olarak tanımlanmış olmalı yani
Edit: Üstte task almamış kopyalarken, tekrar düzelttim o kısmı
public async void AvailableLibraryList(string serverUrl) { var result = await Task.Run(() => helper.GetAvailableLibraries(serverUrl)); }unbalanced tarafından 02/May/15 17:22 tarihinde düzenlenmiştir -
DrKill bunu yazdı
Peki hocamda birşey soracam gönderdiğin kodlarda hata yok mu?
Task[] tasks = new Task[8]
tasks[1].Factory.StartNew(() => {
tasks[2].Factory.StartNew(() => {
şeklinde olmayacak mı? Paralel atama yapmamışsın ki hocam. Sıralı yaptırıyorsun zaten kodlara göre.
Ayrıca 8 tane tasks oluşturma, 8 tane paralel task çalılşacağı anlamına gelmez. İşlemcin mantıksal kaçtane thread destekliyorsa en fazla o kadar prarlel çalışabilirsin. Daha fazlası gerçek manada paralel olmaz. Sadece sanal olarak (simüle edilmiş gibi düşün) paralel olur. Yani biri durur diğeri başlar şeklinde.
Task[] kısmı ile bahsettiğin şey c# ile benim yaptığım şekildede yapabiliyorsun hocam. Derlemede sorun yok.
Aynen dediğine katılıyorum Fiziksel ve Sanal çekirdek mevzularındada bilgim var. 8'i tamamen salladım. Onu daha sonra çalışacağı sunucuda kaç fiziksel çekirden varsa o şekilde çalıştıracak şekilde düzenleyecektim. Ancak bu şekil dede aynı anda birden en azından 2 tane çalışması gerekmez mi?
-
ConcurrentQueue followerIdsArray; public void StartCollect() { Task t = StartCollectAsync(); t.Wait(); } async Task StartCollectAsync() { //.......... var tasks = new List(); for (int i = 0; i < 8; i++) { tasks.Add(collect()); } await Task.WhenAll(tasks); //...... } async Task collect() { Authorizer auther = new Authorizer(); Context context = await auther.getContext(); string pIdStr = ""; do { ConcurrentBag ftsBag = new ConcurrentBag(); List sList = new List(); ulong maxId = 0; ulong pFollowerId = 0; pIdStr = ""; if (fIdsArray.TryDequeue(out pIdStr) == false) break; pFollowerId = Convert.ToUInt64(pIdStr); do { try { if (maxId != 0) { //.... async request sList.AddRange(....); } else { //.... async request sList.AddRange(....); } if (sList.Count > 0) { if (sList.Last() != null) { if (sList.Last().CreatedAt < endUntilDate) break; else { if (sList.Count >= 200) maxId = sList.Last().StatusID - 1; else break; } } else { break; //maxId = 0; } } } catch (Exception ex) { Console.WriteLine(ex); //throw ex; } } while (maxId != 0); sList = sList.Where(x => x.CreatedAt >= startUntilDate && x.CreatedAt <= endUntilDate).ToList(); if (sList.Count > 0) { try { await FTsCollection.InsertManyAsync(sList); Console.WriteLine("Thread ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId); } catch (Exception ex) { log.Info(ex); } } } while (!String.IsNullOrEmpty(pIdStr)); returnŞuanda bu kodu test ediyordum ancak buda tek threadde çalışıyor.
İşlemcim i5-3230, Device Manager'dan bakınca 4 processor listeleniyor.
TeRRoR tarafından 02/May/15 17:36 tarihinde düzenlenmiştir -
delegate , delagete kullanmak zorundasın.
thread vs.. hikaye. delegate ile multitask yapılır. diğer şekilde sürekli zikzak hataları çıkar.
-
BenEfsaneyim bunu yazdı
delegate , delagete kullanmak zorundasın.
thread vs.. hikaye. delegate ile multitask yapılır. diğer şekilde sürekli zikzak hataları çıkar.
delegate mi kaldı hocam? :) biraz geriden takip ediyorsun .net i :) Action /Funct a bak. Asenkron programlama diye bir şey var..
Ayrıca thread e neden hikaye dedin :) Kullanmasını bilmiyorsan zigzag da çizersin çember de :)
unbalanced tarafından 10/May/15 19:35 tarihinde düzenlenmiştir -
asenkron gidecek ise islerin
Thread x1 = new Thread(new ThreadStart(collectData));
x1.Start();
Thread x2 = new Thread(new ThreadStart(collectData));
x2.Start();
Thread x3 = new Thread(new ThreadStart(collectData));
x3.Start();
seklinde yapsan yetmez mi ?
