Parametreleri olan ThreadStart


261

C # 'da parametrelerle bir iş parçacığını nasıl başlatırsınız?


Bu sorunun cevabı, çalışma zamanının sürümleri arasında büyük farklılıklar gösteriyor - 3.5 cevap para cezası mı?
quillbreaker

4
Vay. Eski sorularınızdan bazılarını düzenliyorum, ancak bu tam zamanlı bir iş olabilir. Yıllar boyunca ne kadar iyileştiğini unuttum. :-)
John Saunders

Böyle kısa bir soru sorduğumda, 5 veya daha fazla olumsuz puan alırdım! Her ne kadar soru ve cevap bana yardımcı oldu.
Mohammad Musavi

Yanıtlar:


174

Evet:

Thread t = new Thread (new ParameterizedThreadStart(myMethod));
t.Start (myParameterObject);

14
bu aynıdır: ThreadStart processTaskThread = delegate {ProcessTasks (databox.DataboxID); }; new Thread (processTaskThread) .Start ();
JL.

43
MyParamObject ve myUrl nedir?
dialex

3
Bu durumda void MyParamObject(object myUrl){ //do stuff }parametre tipi olmalıdırobject
Elshan,

15
-1 çünkü cevap, OP'nin ParameterizedThreadStartsoru metninin nasıl kullanılacağını bildiğini varsayar ve muhtemelen böyle değildir.
JYelton

2
Bu hatayı aldım Hata CS0123 'UpdateDB' için aşırı yük yok delege 'ParameterizedThreadStart'
Omid Farvid

482

İş parçacığı yapıcısının 2 aşırı yüklenmesinden biri, başlatma yöntemine tek bir parametre iletmenize izin veren bir ParameterizedThreadStart delegesi alır. Ne yazık ki sadece tek bir parametreye izin veriyor ve bunu güvenli olmayan bir şekilde yapıyor çünkü nesne olarak geçiriyor. İlgili parametreleri yakalamak ve bunları güçlü bir şekilde yazılmış bir şekilde geçirmek için bir lambda ifadesi kullanmak çok daha kolay buluyorum.

Takip etmeyi dene

public Thread StartTheThread(SomeType param1, SomeOtherType param2) {
  var t = new Thread(() => RealStart(param1, param2));
  t.Start();
  return t;
}

private static void RealStart(SomeType param1, SomeOtherType param2) {
  ...
}

41
+1: Şu anda seçili cevap kesinlikle doğru olsa da, JaredPar'dan gelen cevap daha iyidir. Çoğu pratik durum için en iyi çözümdür.
galaktor

2
Bu çözüm, parametreden çok daha iyi ParameterizedThreadStart
Piotr Owsiak

5
Çok basit. Herhangi bir çağrıyı "yeni Konu (() => FooBar ()) .Start ();
Thomas Jespersen

12
Harika, bu VB.NET çocuklar içinDim thr As New Thread(Sub() DoStuff(settings))
dr. kötü

3
@bavaza Sadece statik tip kontrolüne atıfta bulunuyordum
JaredPar

141

Lambda ifadelerini kullanabilirsiniz

private void MyMethod(string param1,int param2)
{
  //do stuff
}
Thread myNewThread = new Thread(() => MyMethod("param1",5));
myNewThread.Start();

bu şimdiye kadar bulabildiğim en iyi cevap, hızlı ve kolay.


6
Basit vakalar için en iyi çözüm IMO
Dunc'ın

1
bu nedir =>? ve sözdizimi hakkında daha fazla bilgiyi nerede bulabilirim?
Nick

2
Bu bir lambda ifadesidir, bazı adresler şu adreslerde bulunabilir: msdn.microsoft.com/en-us/library/vstudio/bb397687.aspx | codeproject.com/Articles/24255/ Keşif-Lambda-İfade-in-C | dotnetperls.com/lambda
Georgi-it

1
Bu benim için çalıştı. ParameterizedThreadStart ve varyasyonlarını denedim ama hiçbir sevinç yoktu. .NET Framework 4'ü basit bir konsol uygulamasında kullanıyordum.
Daniel Hollinrake

Bu, bu tür delegelere alışkın olanlar için en iyi sonucu verir. Yeni başlayanların başını dikmesi zor olabilir. Bu olsa C # standartları için temiz. Kabul edilen cevap benim için çalışmıyor ve nedenini bulmak için zamanım yok.
Bitterblue

37
Thread thread = new Thread(Work);
thread.Start(Parameter);

private void Work(object param)
{
    string Parameter = (string)param;
}

Parametre tipi bir nesne olmalıdır.

DÜZENLE:

Bu cevap yanlış olmasa da bu yaklaşıma karşı öneriyorum. Bir lambda ifadesi kullanmak çok daha kolaydır ve tür dökümü gerektirmez. Buraya bakın: https://stackoverflow.com/a/1195915/52551


Neden derlemeyen bir kod ile yardımcı oluyorsunuz;) Parameter?
Sebastian Xawery Wiśniowiecki

32
class Program
{
    static void Main(string[] args)
    {
        Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod));

        t.Start("My Parameter");
    }

    static void ThreadMethod(object parameter)
    {
        // parameter equals to "My Parameter"
    }
}

3
Bu bana '' DoWork '' delege 'System.Threading.ParameterizedThreadStart' için aşırı yük yok
anon58192932

1
Thread t başlatmasında az önce ThreadMethod'u geçseydiniz ne fark olurdu?
Joe

Unutmayın, parametre tipi 'Nesne' Türü olmalıdır
Kunal Uppal

28

Lambda kullanarak böyle basit bir şekilde ..

Thread t = new Thread(() => DoSomething("param1", "param2"));
t.Start();

YA hatta verebilir delegatekullanarak ThreadStartşöyle ...

ThreadStart ts = delegate
{
     bool moreWork = DoWork("param1", "param2", "param3");
     if (moreWork) 
     {
          DoMoreWork("param4", "param5");
     }
};
new Thread(ts).Start();

VEYA VS 2019 .NET 4.5+ kullanarak bile daha temiz ..

private void DoSomething(int param1, string param2)
{
    //DO SOMETHING..
    void ts()
    {
        if (param1 > 0) DoSomethingElse(param2, "param3");
    }
    new Thread(ts).Start();
    //DO SOMETHING..
}



6

Burada çeşitli cevaplarda daha önce de belirtildiği gibi, Threadsınıf şu anda (4.7.2) birkaç kurucu ve Startaşırı yük içeren bir yöntem sunmaktadır.

Bu soru için bu ilgili kurucular:

public Thread(ThreadStart start);

ve

public Thread(ParameterizedThreadStart start);

ya bir ThreadStartdelege ya da bir ParameterizedThreadStartdelege alır.

Karşılık gelen delegeler şöyle görünür:

public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);

Görülebileceği gibi, kullanılacak doğru kurucu bir ParameterizedThreadStarttemsilci alan kişi gibi görünmektedir, böylece temsilci tarafından belirtilen imzayla uyumlu bazı yöntemler iş parçacığı tarafından başlatılabilir.

ThreadSınıfı örneklemek için basit bir örnek

Thread thread = new Thread(new ParameterizedThreadStart(Work));

ya da sadece

Thread thread = new Thread(Work);

İlgili yöntemin imzası ( Workbu örnekte denir ) şöyle görünür:

private void Work(object data)
{
   ...
}

Geriye kalan, iş parçacığını başlatmaktır. Bu, aşağıdakilerden birini kullanarak yapılır:

public void Start();

veya

public void Start(object parameter);

İken Start()açtığınızda, gerekli geçerdi nullyönteme veri olarak, Start(...)geçmek kullanılabilir şey içine Workiplik yöntemi.

Ancak bu yaklaşımda büyük bir sorun var: WorkYönteme aktarılan her şey bir nesneye dökülüyor. Bu, Workyöntem içinde, aşağıdaki örnekte olduğu gibi tekrar orijinal türe çevrilmesi gerektiği anlamına gelir :

public static void Main(string[] args)
{
    Thread thread = new Thread(Work);

    thread.Start("I've got some text");
    Console.ReadLine();
}

private static void Work(object data)
{
    string message = (string)data; // Wow, this is ugly

    Console.WriteLine($"I, the thread write: {message}");
}



Döküm genellikle yapmak istemediğiniz bir şeydir.

Birisi dize olmayan başka bir şey geçerse ne olur? Bu ilk başta mümkün görünmediği için (çünkü bu benim yöntemim, ne yaptığımı biliyorum veya yöntem özel, birisi ona herhangi bir şeyi nasıl geçebilir? ) Muhtemelen çeşitli nedenlerden dolayı tam olarak bu dava ile sonuçlanabilir . Bazı vakalar sorun yaratmayabileceğinden diğerleri. Bu gibi durumlarda muhtemelen birInvalidCastException iş parçacığını sonlandırdığı için muhtemelen fark etmeyeceğiniz sonuç alırsınız.

Bir çözüm olarak bir jenerik olsun beklenir ParameterizedThreadStartgibi temsilci ParameterizedThreadStart<T>nereye Tsen geçirmek istediğiniz türde veriler olacağını Workyöntemle. Ne yazık ki böyle bir şey henüz yok (henüz?).

Ancak , bu soruna önerilen bir çözüm vardır . İş parçacığına iletilecek verileri ve bunun gibi işçi yöntemini temsil eden yöntemi içeren bir sınıf oluşturmayı içerir:

public class ThreadWithState
{
    private string message;

    public ThreadWithState(string message)
    {
        this.message = message;
    }

    public void Work()
    {
        Console.WriteLine($"I, the thread write: {this.message}");
    }
}

Bu yaklaşımla iş parçacığını şöyle başlatacaksınız:

ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);

thread.Start();

Böylece bu şekilde döküm yapmaktan kaçınır ve bir iş parçacığına veri sağlamanın tipik bir yoluna sahip olursunuz ;-)


Vay be, yorum yapmadan bir downvote ... Ya cevabım oyuncular kadar kötü ya da okuyucu burada işaret etmeye çalıştığım şeyi anlamadı ;-)
Markus Safar

1
Çözümünüzü çok aydınlatıcı buldum, tebrikler. Sadece Net.Core zaten test ettik eklemek ve istekli döküm explicity olmadan çalıştı eklemek istedim! :-) private static void MyMethod<T>(T myData) { T message = myData; Console.WriteLine($"the thread wrote: {message}"); }
Paul Efford

@PaulEfford Teşekkürler ;-) Çözümünüz oldukça hoş görünüyor. Ancak yine de bir nesneye kutulanmış olacağı için belirli bilgilere yazamazsınız, değil mi? (örneğin message.Lengthmümkün değildir ve benzeri)
Markus Safar

1
right ... gibi message.GetType () ve cast gibi belirli bir özellik gerekli if(myData.GetType() == typeof(string)) { var str = ((string)(object)myData).Length; }. Her neyse, diş açma yönteminizi kullanmak yerine, kullanımı biraz daha rahat buldum Tasks<T>, örneğin tasks.Add(Task.Run(() => Calculate(par1, par2, par3))), aşağıdaki cevabımı görün ( stackoverflow.com/a/59777250/7586301 )
Paul Efford

5

Geçirilen parametrede sorun yaşıyordum. Bir for döngüsünden işleve tam sayı geçtim ve gösterdim, ancak her zaman farklı sonuçlar verdi. ParametrizedThreadStart delegesi ile (1,2,2,3) (1,2,3,3) (1,1,2,3) vb .

bu basit kod bir cazibe olarak çalıştı

Thread thread = new Thread(Work);
thread.Start(Parameter);

private void Work(object param) 
{
 string Parameter = (string)param; 
}

4

ParameterizedThreadStartBir parametre alır. Bunu bir parametre veya birkaç özellik içeren özel bir sınıf göndermek için kullanabilirsiniz.

Başka bir yöntem, örnek olarak başlatmak istediğiniz yöntemi, ayarlamak istediğiniz parametrelerin özellikleriyle birlikte bir sınıfa yerleştirmektir. Sınıfın bir örneğini oluşturun, özellikleri ayarlayın ve örneği ve yöntemi belirten iş parçacığını başlatın; yöntem özelliklere erişebilir.


3

ParametrizedThreadStart delegesi kullanabilirsiniz :

string parameter = "Hello world!";
Thread t = new Thread(new ParameterizedThreadStart(MyMethod));
t.Start(parameter);


1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApp6
{
    class Program
    {
        static void Main(string[] args)
        {

            int x = 10;
            Thread t1 =new Thread(new ParameterizedThreadStart(order1));
            t1.IsBackground = true;//i can stope 
            t1.Start(x);

            Thread t2=new Thread(order2);
            t2.Priority = ThreadPriority.Highest;
            t2.Start();

            Console.ReadKey();
        }//Main

        static void  order1(object args)
        {
            int x = (int)args;


                for (int i = 0; i < x; i++)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write(i.ToString() + " ");
            }
        }

        static void order2()
        {
            for (int i = 100; i > 0; i--)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write(i.ToString() + " ");
            }
        }`enter code here`
    }
}

0

Bunun Task<T>yerine kullanmayı öneririm Thread; birden fazla parametreye izin verir ve gerçekten iyi çalışır.

İşte çalışan bir örnek:

    public static void Main()
    {
        List<Task> tasks = new List<Task>();

        Console.WriteLine("Awaiting threads to finished...");

        string par1 = "foo";
        string par2 = "boo";
        int par3 = 3;

        for (int i = 0; i < 1000; i++)
        {
            tasks.Add(Task.Run(() => Calculate(par1, par2, par3))); 
        }

        Task.WaitAll(tasks.ToArray());

        Console.WriteLine("All threads finished!");
    }

    static bool Calculate1(string par1, string par2, int par3)
    {
        lock(_locker)
        {
            //...
            return true;
        }
    }

    // if need to lock, use this:
    private static Object _locker = new Object();"

    static bool Calculate2(string par1, string par2, int par3)
    {
        lock(_locker)
        {
            //...
            return true;
        }
    }

-2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApp6
{
    class Program
    {
        static void Main(string[] args)
        {

            int x = 10;
            Thread t1 =new Thread(new ParameterizedThreadStart(order1));
            t1.Start(x);

            Thread t2=new Thread(order2);
            t2.Priority = ThreadPriority.Highest;
            t2.Start();

            Console.ReadKey();
        }//Main

        static void  order1(object args)
        {
            int x = (int)args;


            for (int i = 0; i < x; i++)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write(i.ToString() + " ");
            }
        }

        static void order2()
        {
            for (int i = 100; i > 0; i--)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write(i.ToString() + " ");
            }
        }
    }
}

C # İş Parçacıkları ile çoklu iş parçacığı, paylaşılan bellekle eşitleme konusunda daha verimli uygulamalar geliştirmenizi sağlar.
Muhammed Hassen İsmaile
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.