Helpex - Trao đổi & giúp đỡ Đăng nhập
262

Làm thế nào để truyền tham số cho Thread.ThreadStart()phương thức trong C #?

Giả sử tôi có phương pháp gọi là 'tải xuống'

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

Bây giờ tôi đã tạo một chủ đề trong phương thức chính:

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

loại phương pháp lỗi dự kiến.

Làm thế nào tôi có thể truyền tham số cho ThreadStartphương thức đích với tham số?

262 hữu ích 1 bình luận 327k xem chia sẻ
641

Đơn giản nhất là

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

Ưu điểm của (hơn ParameterizedThreadStart) này là bạn có thể truyền nhiều tham số và bạn có thể kiểm tra thời gian biên dịch mà không cần phải truyền từ objectmọi lúc.

641 hữu ích 5 bình luận chia sẻ
33

Nhìn vào ví dụ này:

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

public void WorkerMethod(object parameterObject)
{
    // do your job!
}

Trước tiên, bạn tạo một luồng bằng cách chuyển ủy nhiệm cho phương thức worker và sau đó khởi động nó bằng phương thức Thread.Start lấy đối tượng của bạn làm tham số.

Vì vậy, trong trường hợp của bạn, bạn nên sử dụng nó như thế này:

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

Nhưng phương thức 'tải xuống' của bạn vẫn cần lấy đối tượng , không phải chuỗi như một tham số. Bạn có thể truyền nó thành chuỗi trong cơ thể phương thức của bạn.

33 hữu ích 2 bình luận chia sẻ
20

Bạn muốn sử dụng ParameterizedThreadStartủy nhiệm cho các phương thức luồng lấy tham số. (Hoặc không có gì thực sự, và để cho nhà Threadxây dựng suy luận.)

Ví dụ sử dụng:

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

thread.Start(filename)
20 hữu ích 0 bình luận chia sẻ
4

Bạn cũng có thể delegatethích như vậy ...

ThreadStart ts = delegate
{
      bool moreWork = DoWork("param1", "param2", "param3");
      if (moreWork) 
      {
          DoMoreWork("param1", "param2");
      }
};
new Thread(ts).Start();
4 hữu ích 0 bình luận chia sẻ
2

Bạn có thể đóng gói hàm luồng (tải xuống) và (các) tham số cần thiết (tên tệp) trong một lớp và sử dụng ủy quyền ThreadStart để thực thi chức năng luồng.

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);
2 hữu ích 1 bình luận chia sẻ
1

Bổ sung

    Thread thread = new Thread(delegate() { download(i); });
    thread.Start();
1 hữu ích 0 bình luận chia sẻ
0

Làm thế nào về điều này: (hoặc nó là ok để sử dụng như thế này?)

var test = "Hello";
new Thread(new ThreadStart(() =>
{
    try
    {
        //Staff to do
        Console.WriteLine(test);
    }
    catch (Exception ex)
    {
        throw;
    }
})).Start();
0 hữu ích 0 bình luận chia sẻ
0

Theo câu hỏi của bạn ...

Làm cách nào để truyền tham số cho phương thức Thread.ThreadStart () trong C #?

... và lỗi bạn gặp phải, bạn sẽ phải sửa mã của mình từ

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

đến

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



Tuy nhiên, câu hỏi phức tạp hơn lúc đầu.

Các Threadlớp học hiện nay (4.7.2) cung cấp một số nhà xây dựng và một Startphương pháp với quá tải.

Những nhà xây dựng có liên quan cho câu hỏi này là:

public Thread(ThreadStart start);

public Thread(ParameterizedThreadStart start);

trong đó có một ThreadStartđại biểu hoặc một ParameterizedThreadStartđại biểu.

Các đại biểu tương ứng trông như thế này:

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

Vì vậy, như có thể thấy, hàm tạo chính xác để sử dụng dường như là hàm lấy một ParameterizedThreadStartđại biểu để một số phương thức phù hợp với chữ ký được chỉ định của đại biểu có thể được bắt đầu bởi luồng.

Một ví dụ đơn giản để kích hoạt Threadlớp học sẽ là

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

hoặc chỉ

Thread thread = new Thread(Work);

Chữ ký của phương thức tương ứng (được gọi Worktrong ví dụ này) trông như thế này:

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

Những gì còn lại là bắt đầu chuỗi. Điều này được thực hiện bằng cách sử dụng một trong hai

public void Start();

hoặc là

public void Start(object parameter);

Trong khi Start()sẽ bắt đầu luồng và truyền nulldưới dạng dữ liệu cho phương thức, Start(...)có thể được sử dụng để truyền bất cứ thứ gì vào Workphương thức của luồng.

Tuy nhiên, có một vấn đề lớn với cách tiếp cận này: Mọi thứ được truyền vào Workphương thức đều được đưa vào một đối tượng. Điều đó có nghĩa là trong Workphương thức nó phải được chuyển sang loại ban đầu như trong ví dụ sau:

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



Đúc là điều bạn thường không muốn làm.

Điều gì xảy ra nếu ai đó vượt qua một thứ khác không phải là một chuỗi? Vì điều này ban đầu dường như là không thể (vì đó là phương pháp của tôi, tôi biết tôi làm gì hoặc Phương pháp này là riêng tư, làm thế nào để ai đó có thể truyền bất cứ điều gì cho nó? ) Bạn có thể kết thúc chính xác với trường hợp đó vì nhiều lý do . Vì một số trường hợp có thể không phải là một vấn đề, những người khác là. Trong những trường hợp như vậy, bạn có thể sẽ kết thúc với một InvalidCastExceptioncái mà bạn có thể sẽ không nhận thấy vì nó chỉ đơn giản là chấm dứt chuỗi.

Là một giải pháp mà bạn mong đợi để có được một ParameterizedThreadStartđại biểu chung giống như ParameterizedThreadStart<T>nơi Tsẽ là loại dữ liệu bạn muốn truyền vào Workphương thức. Thật không may, một cái gì đó như thế này không tồn tại (chưa?).

Tuy nhiên, có một giải pháp được đề xuất cho vấn đề này. Nó liên quan đến việc tạo một lớp chứa cả hai, dữ liệu được truyền đến luồng cũng như phương thức đại diện cho phương thức worker như thế này:

public class ThreadWithState
{
    private string message;

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

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

Với phương pháp này, bạn sẽ bắt đầu chuỗi như thế này:

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

thread.Start();

Vì vậy, theo cách này, bạn chỉ cần tránh truyền xung quanh và có một cách an toàn để cung cấp dữ liệu cho một chuỗi ;-)

0 hữu ích 0 bình luận chia sẻ
1

đây là cách hoàn hảo ...

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);
}
1 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ c# .net multithreading , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading