Duyuruyu Kapat
Facebook Gözat
Twitter Gözat

Önemli Bir Probem Thread

Konu, 'C#' kısmında Alibudur tarafından paylaşıldı.

  1. Alibudur

    Alibudur Yeni Üye

    Kayıt:
    10 Şubat 2014
    Mesajlar:
    4
    Beğenilen Mesajlar:
    0
    Arkadaşlar iyi günler önemli bir sorunum var, programımızı kodlarken programımızda birden fazla işlem nasıl gerçekleştirebiliriz donmadan sorunsuz bir şekilde..

    Şöyle diyelim; bir listview'e 500.000 adet itemlar ekliycem bir taraftan program hiç bir şekilde donyamayacak ve kullanıcı listboxa 500.000 adet dosyadan veri okuyacak.

    Bu tür işlemleri donmadan nasıl yapabiliriz, eş zamanlı ve thread yaparak denedim lakin olmuyor uygulayamıyorum bilgim dahilinde, bu arada bu işlemi "BackgroundWorker" kullanmadan yapmak istiyorum... yardımcı olursanız sevirinim...

     
  2. overloader

    overloader Üye

    Kayıt:
    25 Haziran 2013
    Mesajlar:
    25
    Beğenilen Mesajlar:
    0
    Meslek:
    Yazılım Uzmanı
    Şehir:
    istanbul
  3. Furkan Onka Uğur

    Furkan Onka Uğur Moderatör Yetkili Kişi

    Kayıt:
    12 Eylül 2008
    Mesajlar:
    3,624
    Beğenilen Mesajlar:
    23
    Şehir:
    Ankara
    doevents çok yavaşlatır. En kolayı backgroundworker ile olur. Neden kullanmak istemiyorsunuz? Thread ile
    Kod:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    
    namespace ThreadTest01
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
    
            private void button1_Click(object sender, EventArgs e)
            {
                Thread thread = new Thread(doldur);
                thread.Start();
    
    
            }
    
    
    
    
            private void doldur()
            {
                for (int i = 0; i < 500000; i++)
                {
                    if (listBox1.InvokeRequired)
                    {
                        listBox1.Invoke((MethodInvoker)
                            (() =>
                            {
                                listBox1.Items.Add(i.ToString());
                            })
                            );
                    }
                    else
                    {
                        listBox1.Items.Add(i.ToString());
                    }
                }
            }
        }
    }
    
    
     
  4. DeepSoMania

    DeepSoMania Yeni Üye

    Kayıt:
    20 Mart 2009
    Mesajlar:
    14
    Beğenilen Mesajlar:
    6
    Meslek:
    Senior Developer
    Şehir:
    Münster
    Merhaba,

    konuya yorum yapmamın amacı, bakıldığında seçenek olması açısındandır. Yoksa cevap veren arkadaşlarım güzel bilgiler vermiş.

    1- İlk olarak verilerini bir ListBox'a alacaksın ve yüklü miktarda verilerin var. Önerilerimden birtanesi ilk olarak DataView sınıfını kullanman olacak. Bu sınıf özelliklerinin ve sorgulama sisteminin başarılı olduğunu biliyorum. Veriyi ilgili yerden çektikten sonra bir DataView sınıfına yükle. Hem sorgulama açısından işini kriz çıkmadan yapacaktır, hem de yeteneklerini geliştirebilme açısından. Bunu önermemin amacı muhtemelen bir sorgu da yapacağını tahmin etmemdir.

    2- Thread konusuna gelince, bu kısımda anlamadığım yer; neden özellikle bir Thread kullanma isteğin var. Bu konudaki tavsiyem ise kesinlikle Parallel.For olacaktır. Örnek kodlarına gelince;

    Elimizde seri işlem yapan kodlar var;

    Kod:
    public class SeriallProcess
    {
    public void Run(int times=30)
    {
    Console.WriteLine("Serial Process");
    Stopwatch time = new Stopwatch(); //using System.Diagnostics;
    time.Start();
    for (int i = 2; i < times; i++)
    {
    var result = sum(i);
    Console.WriteLine($"root : {i} : {result} Thread : {Thread.CurrentThread.ManagedThreadId}");
    }
    Console.WriteLine($"Total Time : {time.ElapsedMilliseconds} millisecond");
    Console.Read();
    }
    private double sum(int root)
    {
    double result = 0;
    for (int i = 0; i < 10000; i++)
    {
    result += (1 / Math.Sqrt(2 * Math.PI)) * Math.Exp(0.5 * Math.Pow(root, 2));
    }
    return result;
    }
    }
    
    Elimizde paralel işlemler için kodlar var;

    Kod:
    public class ParallelProcess
    {
    public void Run(int times = 30)
    {
    Console.WriteLine("Parallel Process");
    Stopwatch time = new Stopwatch(); //using System.Diagnostics;
    time.Start();
    Parallel.For(2, times, i =>
    {
    var result = sum(i);
    Console.WriteLine($"root : {i} : {result} Thread : {Thread.CurrentThread.ManagedThreadId}");
    });
    Console.WriteLine($"Total Time : {time.ElapsedMilliseconds} millisecond");
    Console.Read();
    }
    private double sum(int root)
    {
    double result = 0;
    for (int i = 0; i < 10000; i++)
    {
    result += (1 / Math.Sqrt(2 * Math.PI)) * Math.Exp(0.5 * Math.Pow(root, 2));
    }
    return result;
    }
    }
    
    Birde bu iki sınıfı kullanan ana sınıfımız var,
    
    [CODE]
    static void Main(string[] args)
    {
    SeriallProcess serialProcess = new SeriallProcess();
    ParallelProcess parallelProcess = new ParallelProcess();
    
    serialProcess.Run(30); //30 sefer => 30.000 sefer = ~27 milisaniye
    parallelProcess.Run(30); //30 sefer => 30.000 sefer = ~105 milisaniye
    
    serialProcess.Run(100); //100 sefer => 100.000 sefer = ~297 milisaniye !!!
    parallelProcess.Run(100); //100 sefer => 100.000 sefer = ~175 milisaniye !!!
    
    Console.Read();
    }
    
    Dikkat edilirse 30 bin işlemde kesinlikle Thread açık ara ile önde. Ancak veri boyutları yükseldikçe
    Parallel yapının açık ara öne geçtiğini görebiliriz.

    Yukarıda kullanılan sum methodu için kullanılan fonksiyon : Standard Normal Distribution.

    [​IMG]

    Yanlış hatırlamıyorsam notlarım arasında bulamadım ama bu bilgilerin bir kısmını internet üzerinde
    Türkçe bir siteden de faydalanmıştım.

    ---------------------------------------------------------

    İkinci örneğimiz dosyalar üzerinde işlem yapma. (Bir arkadaşıma Vb.NET ile destek olmak için yazılan bir örnekti.)

    4 Adet klasörüm var ve her klasörüm 10.000 adet text dosyasına sahip. 1 adet text dosyasının büyüklüğü : 321 KB
    Her text dosyamızda aranan "__LOCAL_SIZE" ve her bir text dosyasında değişik satırlarda 540 adet "__LOCAL_SIZE"
    kelimesi bulunmaktadır.

    Thread ile denenmesi :
    Başlangıç saati : 01:25:35
    Bitiş saati : 02:30:00 (İşlemler devam ettiğinden ben manual olarak durdurmak zorunda kaldım..)


    Parallel ile denenmesi :
    Sadece 11 dakika 28 saniye sürdü..

    Örnek Vb.NET kodları aşağıdadır:

    Kod:
    Module Module1
    
    Sub Main()
    
    ' FOLDER & FILE INFORMATION
    '----------------------------------------
    'Total Size : ~12.2 / ~12.3 GB
    'Folder 1 : TestFolder (10.000 text file)
    'Folder 2 : TestFolder (10.000 text file)
    'Folder 3 : TestFolder (10.000 text file)
    'Folder 4 : TestFolder (10.000 text file)
    '1 Text file is 321 KB (Size / Grösse)
    
     
    'ReadOperation_Invoke()
    
    Dim mre As New ManualResetEvent(False)
    Dim timeInfo As Stopwatch = New Stopwatch()
    timeInfo.Start()
    
    
    'Sadece 00:11:28.1244486 Dakika
    Parallel_ReadOperation_with_Function("D:\Test\TPL_Test")
    
    'Thread_ReadOperation_with_Function :
    'Start : 01:25:35.0000000
    'End : 02:30:00.0000000 (Uzun sürdüğünden durdurmak zorunda kaldım)
    Thread_ReadOperation_with_Function()
    mre.WaitOne()
    
    'Parallel Invoke technique
    
    Parallel_Invoke_ReadOperation() 'Bu kısımda Parallel yapısı içinden farklı bir Invoke tekniği kullandım ancak yinede Thread gibi uzun sürüyor.

    Kod:
    timeInfo.Stop()
    
    Console.WriteLine("Four Thread Time elapsed for 40.000 text files : {0}", timeInfo.Elapsed)
    
    Console.Read()
    End Sub
    
    Sub Parallel_ReadOperation_with_Function(folderMap As String)
    
    Dim files() As String = IO.Directory.GetFiles(folderMap, "*.txt", IO.SearchOption.AllDirectories)
    Dim line As String = String.Empty
    Dim timeInfo As Stopwatch = New Stopwatch()
    
    timeInfo.Start()
    
    Parallel.For(0, files.Length, Sub(i As Integer)
      Dim reader As System.IO.StreamReader = New IO.StreamReader(files(i))
      line = String.Empty
    
      line = reader.ReadToEnd()
    
      If (line.Contains("__LOCAL_SIZE")) Then
      Console.WriteLine("File Location : {0}", files(i))
      End If
    
      Thread.Sleep(2000) 'wait for other operation
      reader.Close()
      reader.Dispose()
    
      End Sub)
    
    timeInfo.Stop()
    
    Console.WriteLine("One Parallel Time elapsed for 40.000 text files : {0}", timeInfo.Elapsed)
    
    End Sub
    
    Sub Thread_ReadOperation_with_Function()
    Dim line As String = String.Empty
    
    Dim thread1 As New Thread(Sub()
    
      For Each file As String In IO.Directory.GetFiles("D:\Test\TPL_Test\TestFolder1", "*.txt", IO.SearchOption.AllDirectories)
      Dim reader As System.IO.StreamReader = New IO.StreamReader(file)
      line = String.Empty
    
      line = reader.ReadToEnd()
    
      If (line.Contains("__LOCAL_SIZE")) Then
      Console.WriteLine("File Location : {0}", file)
      End If
    
      Thread.Sleep(2000) 'wait for other operation
      reader.Close()
      reader.Dispose()
    
      Next
    
      End Sub)
    
    
    Dim thread2 As New Thread(Sub()
    
      For Each file As String In IO.Directory.GetFiles("D:\Test\TPL_Test\TestFolder2", "*.txt", IO.SearchOption.AllDirectories)
      Dim reader As System.IO.StreamReader = New IO.StreamReader(file)
      line = String.Empty
    
      line = reader.ReadToEnd()
    
      If (line.Contains("__LOCAL_SIZE")) Then
      Console.WriteLine("File Location : {0}", file)
      End If
    
      Thread.Sleep(2000) 'wait for other operation
      reader.Close()
      reader.Dispose()
    
      Next
    
      End Sub)
    
    Dim thread3 As New Thread(Sub()
    
      For Each file As String In IO.Directory.GetFiles("D:\Test\TPL_Test\TestFolder3", "*.txt", IO.SearchOption.AllDirectories)
      Dim reader As System.IO.StreamReader = New IO.StreamReader(file)
      line = String.Empty
    
      line = reader.ReadToEnd()
    
      If (line.Contains("__LOCAL_SIZE")) Then
      Console.WriteLine("File Location : {0}", file)
      End If
    
      Thread.Sleep(2000) 'wait for other operation
      reader.Close()
      reader.Dispose()
    
      Next
    
      End Sub)
    
    Dim thread4 As New Thread(Sub()
    
      For Each file As String In IO.Directory.GetFiles("D:\Test\TPL_Test\TestFolder4", "*.txt", IO.SearchOption.AllDirectories)
      Dim reader As System.IO.StreamReader = New IO.StreamReader(file)
      line = String.Empty
    
      line = reader.ReadToEnd()
    
      If (line.Contains("__LOCAL_SIZE")) Then
      Console.WriteLine("File Location : {0}", file)
      End If
    
      Thread.Sleep(2000) 'wait for other operation
      reader.Close()
      reader.Dispose()
    
      Next
    
      End Sub)
    
    thread1.Start()
    thread2.Start()
    thread3.Start()
    thread4.Start()
    
    End Sub
    
    
    
    Sub Parallel_Invoke_ReadOperation()
    Dim ReaderFunction1 As Action = Sub()
      Dim line As String = String.Empty
      For Each file As String In IO.Directory.GetFiles("D:\Test\TPL_Test\TestFolder1", "*.txt", IO.SearchOption.AllDirectories)
      Dim reader As System.IO.StreamReader = New IO.StreamReader(file)
      line = String.Empty
    
      line = reader.ReadToEnd()
    
      If (line.Contains("__LOCAL_SIZE")) Then
      Console.WriteLine("File Location : {0}", file)
      End If
    
      Thread.Sleep(2000) 'wait for other operation
      reader.Close()
      reader.Dispose()
    
      Next
      End Sub
    
    Dim ReaderFunction2 As Action = Sub()
      Dim line As String = String.Empty
      For Each file As String In IO.Directory.GetFiles("D:\Test\TPL_Test\TestFolder2", "*.txt", IO.SearchOption.AllDirectories)
      Dim reader As System.IO.StreamReader = New IO.StreamReader(file)
      line = String.Empty
    
      line = reader.ReadToEnd()
    
      If (line.Contains("__LOCAL_SIZE")) Then
      Console.WriteLine("File Location : {0}", file)
      End If
    
      Thread.Sleep(2000) 'wait for other operation
      reader.Close()
      reader.Dispose()
    
      Next
      End Sub
    
    Dim ReaderFunction3 As Action = Sub()
      Dim line As String = String.Empty
      For Each file As String In IO.Directory.GetFiles("D:\Test\TPL_Test\TestFolder3", "*.txt", IO.SearchOption.AllDirectories)
      Dim reader As System.IO.StreamReader = New IO.StreamReader(file)
      line = String.Empty
    
      line = reader.ReadToEnd()
    
      If (line.Contains("__LOCAL_SIZE")) Then
      Console.WriteLine("File Location : {0}", file)
      End If
    
      Thread.Sleep(2000) 'wait for other operation
      reader.Close()
      reader.Dispose()
    
      Next
      End Sub
    
    Dim ReaderFunction4 As Action = Sub()
      Dim line As String = String.Empty
      For Each file As String In IO.Directory.GetFiles("D:\Test\TPL_Test\TestFolder4", "*.txt", IO.SearchOption.AllDirectories)
      Dim reader As System.IO.StreamReader = New IO.StreamReader(file)
      line = String.Empty
    
      line = reader.ReadToEnd()
    
      If (line.Contains("__LOCAL_SIZE")) Then
      Console.WriteLine("File Location : {0}", file)
      End If
    
      Thread.Sleep(2000) 'wait for other operation
      reader.Close()
      reader.Dispose()
    
      Next
      End Sub
    
    Parallel.Invoke(ReaderFunction1, ReaderFunction2, ReaderFunction3, ReaderFunction4)
    End Sub
    
    
    
    
    End Module
    
    Not : Kodları direkt olarak kopyalayıp buraya yapıştırdım. Kodlar çalıştırılıp test edilmiştir.
    Yanlışlık gördüğünüz bir yeri belirtirseniz de sevinirim.

    Saygılarımla
     
  5. MakPRO

    MakPRO Üye

    Kayıt:
    15 Mayıs 2007
    Mesajlar:
    85
    Beğenilen Mesajlar:
    11
    size tavsiyem database ile bu işi hal etmeniz. kaç client için kullanılacak bu sistem bilmiyorum . Ama her client için bu şekilde işlem yaptırırsanız , networkte yavaşlar, işlemcide , ram de.
    SQL ile kendinize bir çözüm arayıp karmaşık algoritmaları database engine yüklemek daha faydalıdır.