থ্রেড স্টার্ট পদ্ধতিতে প্যারামিটারগুলি কীভাবে পাস করবেন?


290

কিভাবে পরামিতি পাস Thread.ThreadStart()সি # পদ্ধতিতে ?

ধরুন আমার কাছে 'ডাউনলোড' নামক পদ্ধতি আছে

public void download(string filename)
{
    // download code
}

এখন আমি মূল পদ্ধতিতে একটি থ্রেড তৈরি করেছি:

Thread thread = new Thread(new ThreadStart(download(filename));

ত্রুটি পদ্ধতি প্রকারের প্রত্যাশিত।

আমি কীভাবে পরামিতিগুলির ThreadStartসাথে লক্ষ্য পদ্ধতিতে পরামিতিগুলি পাস করতে পারি ?


2
জন স্কিটি রচিত এই নিবন্ধটি পরীক্ষা করে দেখুন প্যারামিটার বিভাগটি পরবর্তী পৃষ্ঠায় রয়েছে তবে সামগ্রিকভাবে নিবন্ধটি বেশ ভাল পঠিত।
কোডিংবাজার

উত্তর:


695

সর্বাধিক সরল

string filename = ...
Thread thread = new Thread(() => download(filename));
thread.Start();

এর (ওজনের) সুবিধা ParameterizedThreadStartহ'ল আপনি একাধিক প্যারামিটারগুলি পাস করতে পারেন এবং আপনি objectসমস্ত সময় থেকে toালাই না করেই কম্পাইল-টাইম চেকিং পান ।


15
আমি অফটোপিকের জন্য দুঃখিত তবে '()' অপারেটরের অর্থ কী? আমি এটি মাঝে মাঝে দেখি তবে আমার চেক করার সময় নেই।
asukaszW.pl

24
এটি একটি লাম্বডা প্রকাশ যা কোনও যুক্তি ছাড়াই।
নলডোরিন

31
@ AsukaszW.pl - নলডোরিন যা বলেছিলেন; সি # 2.0 তে পি বিকল্প বিকল্প নির্মাণ (উদাহরণস্বরূপ) হ'লnew Thread(delegate() { download(filename); });
মার্ক গ্র্যাভেল

7
@ টাইমেক এটি পুরোপুরি সঠিক নয়; আটককৃত যেকোন ভেরিয়েবলকে সম্পূর্ণ লেজিকাল ক্লোজার হিসাবে গণ্য করা হয় , যা (বাস্তবায়নের বিশদ হিসাবে) সংকলক-উত্পাদিত শ্রেণীর ক্ষেত্র হিসাবে প্রয়োগ করা হয়। অতিরিক্তভাবে, ক্লোজার স্কোপটি ঘোষণার সুযোগ হিসাবে সংজ্ঞায়িত করা হয়। এটি সত্যিকারের "রেফারেন্স হিসাবে" নয় ("রেফারেন্স দ্বারা পাস" এবং "রেফারেন্সের ধরণগুলি" উভয়ই সংজ্ঞায়িত, এবং সত্যই এই দৃশ্যের বর্ণনা দেয় না)
মার্ক গ্র্যাভেল

5
@ মার্কগ্রাভেল - আপনি সঠিক আমার যা বলা উচিত ছিল তা হ'ল একজনকে সচেতন হওয়া উচিত যে থ্রেড শুরু হওয়ার আগে যদি 'ফাইলের নাম' পরিবর্তন হয় তবে নতুন মানটি ব্যবহৃত হবে। আমি এর মেকানিক্স সম্পর্কে বকবক করা উচিত ছিল না এবং আমি অবশ্যই রেফারেন্সিং সম্পর্কে কথা বলা উচিত নয়।
tymtam

36

এই উদাহরণটি দেখুন:

public void RunWorker()
{
    Thread newThread = new Thread(WorkerMethod);
    newThread.Start(new Parameter());
}

public void WorkerMethod(object parameterObj)
{
    var parameter = (Parameter)parameterObj;
    // do your job!
}

আপনি প্রথমে কর্মী পদ্ধতিতে প্রতিনিধি প্রেরণ করে একটি থ্রেড তৈরি করছেন এবং তারপরে এটি একটি থ্রেড.স্টার্ট পদ্ধতি দিয়ে শুরু করুন যা আপনার অবজেক্টটিকে প্যারামিটার হিসাবে গ্রহণ করে।

সুতরাং আপনার ক্ষেত্রে আপনার এটি ব্যবহার করা উচিত:

    Thread thread = new Thread(download);
    thread.Start(filename);

তবে আপনার 'ডাউনলোড' পদ্ধতির এখনও পরামিতি হিসাবে স্ট্রিং নয়, অবজেক্ট নেওয়া দরকার । আপনি আপনার পদ্ধতির শরীরে স্ট্রিংয়ে কাস্ট করতে পারেন।


25

ParameterizedThreadStartপরামিতিগুলি গ্রহণ করে এমন থ্রেড পদ্ধতির জন্য আপনি প্রতিনিধিটি ব্যবহার করতে চান । (বা আসলে কিছুই নেই, এবং Threadনির্মাতাকে অনুমান করা যাক ))

ব্যবহারের উদাহরণ:

var thread = new Thread(new ParameterizedThreadStart(download));
//var thread = new Thread(download); // equivalent

thread.Start(filename)

7

আপনিও এটি delegateপছন্দ করতে পারেন ...

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


3

আপনি কোনও ক্লাসে থ্রেড ফাংশন (ডাউনলোড) এবং প্রয়োজনীয় প্যারামিটারগুলি (ফাইলের নাম) encapsulate করতে পারেন এবং থ্রেড ফাংশনটি সম্পাদন করতে থ্রেডস্টার্ট প্রতিনিধি ব্যবহার করতে পারেন।

public class Download
{
    string _filename;

    Download(string filename)
    {
       _filename = filename;
    }

    public void download(string filename)
    {
       //download code
    }
}

Download = new Download(filename);
Thread thread = new Thread(new ThreadStart(Download.download);

আমি এই পদ্ধতিটি আরও ভাল পছন্দ করেছি, আমি দেখতে পেয়েছি যে ল্যাম্বডা এক্সপ্রেশন পদ্ধতির সর্বদা সঠিক পরামিতিগুলি ট্র্যাক করা হয় না
মানেবানি

3

আমি আপনাকে ফাইল নামে আরও একটি ক্লাস করার পরামর্শ দিচ্ছি।

public class File
{
   private string filename;

   public File(string filename)
   {
      this.filename= filename;
   }

   public void download()
   {
       // download code using filename
   }
}

এবং আপনার থ্রেড তৈরির কোডে আপনি একটি নতুন ফাইল ইনস্ট্যান্ট করবেন:

string filename = "my_file_name";

myFile = new File(filename);

ThreadStart threadDelegate = new ThreadStart(myFile.download);

Thread newThread = new Thread(threadDelegate);

0

এটি সম্পর্কে কীভাবে: (বা এটির মতো ব্যবহার করা ঠিক আছে?)

var test = "Hello";
new Thread(new ThreadStart(() =>
{
    try
    {
        //Staff to do
        Console.WriteLine(test);
    }
    catch (Exception ex)
    {
        throw;
    }
})).Start();

-1

আপনার প্রশ্ন অনুযায়ী ...

C # তে থ্রেড.ড্রেডস্টার্ট () পদ্ধতিতে কীভাবে প্যারামিটারগুলি পাস করবেন?

... এবং আপনি যে ত্রুটির মুখোমুখি হয়েছিলেন সেখান থেকে আপনাকে আপনার কোডটি সংশোধন করতে হবে

Thread thread = new Thread(new ThreadStart(download(filename));

প্রতি

Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);



তবে প্রশ্নটি প্রথমে যেমনটি মনে হচ্ছে আরও জটিল।

Threadবর্গ বর্তমানে (4.7.2) বিভিন্ন উপলব্ধ কনস্ট্রাকটর এবং Startoverloads সঙ্গে পদ্ধতি।

এই প্রশ্নের জন্য এই প্রাসঙ্গিক নির্মাতারা হলেন:

public Thread(ThreadStart start);

এবং

public Thread(ParameterizedThreadStart start);

যা হয় একটি ThreadStartপ্রতিনিধি বা একটি ParameterizedThreadStartপ্রতিনিধি গ্রহণ।

সংশ্লিষ্ট প্রতিনিধিরা এর মতো দেখায়:

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

যেমন দেখা যায়, সঠিকভাবে নির্মাণকারীর ব্যবহারকারীর ParameterizedThreadStartপ্রতিনিধি নিচ্ছেন বলে মনে হচ্ছে যাতে কোনও পদ্ধতি ডেলিগেটের নির্দিষ্ট স্বাক্ষর অনুসারে থ্রেডের সাহায্যে শুরু করা যায়।

Threadক্লাসটি ইনস্ট্যান্ট করার জন্য একটি সাধারণ উদাহরণ হবে

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

বা শুধু

Thread thread = new Thread(Work);

সংশ্লিষ্ট পদ্ধতির স্বাক্ষর ( Workএই উদাহরণে বলা হয়) এর মতো দেখায়:

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

যা বাকি তা থ্রেড শুরু করা। এটি হয় ব্যবহার করে করা হয়

public void Start();

অথবা

public void Start(object parameter);

যদিও Start()থ্রেড শুরু করা এবং পাস হবে nullপদ্ধতিতে ডেটা, Start(...)পাস ব্যবহার করা যেতে পারে কিছু মধ্যে Workথ্রেডের পদ্ধতি।

এই পদ্ধতির সাথে তবে একটি বড় সমস্যা রয়েছে: Workপদ্ধতিতে পাস করা সমস্ত কিছু একটি বস্তুতে ফেলে দেওয়া হয়। তার মানে হল যে Workপদ্ধতিটির মধ্যে এটি নীচের উদাহরণের মতো আবারও মূল ধরণে ফেলে দিতে হবে:

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}");
}



কাস্টিং এমন একটি জিনিস যা আপনি সাধারণত করতে চান না।

যদি কেউ অন্য কিছু পাস করে যা স্ট্রিং নয়? যেহেতু এটি প্রথমে সম্ভব নয় বলে মনে হয় (কারণ এটি আমার পদ্ধতি, আমি জানি আমি কী করি বা পদ্ধতিটি ব্যক্তিগত, তাই কোনও ব্যক্তির কীভাবে কোনও কিছুতে এটি পাস করা কখনই সক্ষম হওয়া উচিত? ) বিভিন্ন কারণে আপনি সম্ভবত ঠিক সেই ক্ষেত্রেই শেষ করতে পারেন । কিছু ক্ষেত্রে সমস্যা নাও হতে পারে, অন্যরা হ'ল are এই ক্ষেত্রে আপনি সম্ভবত একটি সঙ্গে শেষ হবেInvalidCastException এমনটি যা আপনি সম্ভবত লক্ষ্য করবেন না কারণ এটি কেবল থ্রেডটি বন্ধ করে দেয়।

একটি সমাধান হিসেবে আপনি একটি জেনেরিক পেতে আশা ParameterizedThreadStartমত প্রতিনিধি ParameterizedThreadStart<T>যেখানে Tআপনি মধ্যে পাস করতে চান ডেটার প্রকারের হবে Workপদ্ধতি। দুর্ভাগ্যক্রমে এর মতো কিছু বিদ্যমান নেই (এখনও?)।

তবে এই ইস্যুটির একটি প্রস্তাবিত সমাধান রয়েছে । এটিতে একটি শ্রেণি তৈরি করা রয়েছে যা উভয়ই রয়েছে, ডেটা থ্রেডে পাঠানো হবে পাশাপাশি সেই পদ্ধতি যা শ্রমিকের পদ্ধতিটিকে এভাবে প্রতিনিধিত্ব করে:

public class ThreadWithState
{
    private string message;

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

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

এই পদ্ধতির সাহায্যে আপনি থ্রেডটি এভাবে শুরু করবেন:

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

thread.Start();

সুতরাং এই উপায়ে আপনি কেবল চারপাশে ingালাই এড়ানো এবং কোনও থ্রেডে ডেটা সরবরাহ করার একটি টাইপসেজ উপায় আছে ;-)


-2

এখানে সঠিক উপায় ...

private void func_trd(String sender)
{

    try
    {
        imgh.LoadImages_R_Randomiz(this, "01", groupBox, randomizerB.Value); // normal code

        ThreadStart ts = delegate
        {
            ExecuteInForeground(sender);
        };

        Thread nt = new Thread(ts);
        nt.IsBackground = true;

        nt.Start();

    }
    catch (Exception)
    {

    }
}

private void ExecuteInForeground(string name)
{
     //whatever ur function
    MessageBox.Show(name);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.