Sự khác biệt giữa Invoke () và BeginInvoke ()


398

Chỉ tự hỏi sự khác biệt giữa BeginInvoke()Invoke()là gì?

Chủ yếu là những gì mỗi người sẽ được sử dụng cho.

EDIT: Sự khác biệt giữa việc tạo một đối tượng luồng và gọi invoke trên đó và chỉ gọi BeginInvoke()một đại biểu là gì? chúng giống nhau hả?

Câu trả lời:


568

Bạn có nghĩa là Delegate.Invoke/ BeginInvokehoặc Control.Invoke/ BeginInvoke?

  • Delegate.Invoke: Thực thi đồng bộ, trên cùng một chủ đề.
  • Delegate.BeginInvoke: Thực thi không đồng bộ, trên một threadpoolluồng.
  • Control.Invoke: Thực thi trên luồng UI, nhưng gọi luồng chờ hoàn thành trước khi tiếp tục.
  • Control.BeginInvoke: Thực thi trên luồng UI và luồng gọi không chờ hoàn thành.

Câu trả lời của Tim đề cập đến khi bạn có thể muốn sử dụng BeginInvoke- mặc dù nó chủ yếu hướng đến Delegate.BeginInvoke, tôi nghi ngờ.

Đối với Windows Forms ứng dụng, tôi sẽ đề nghị rằng bạn nên thường sử dụng BeginInvoke. Bằng cách đó, bạn không cần phải lo lắng về sự bế tắc, chẳng hạn - nhưng bạn cần hiểu rằng UI có thể chưa được cập nhật vào lần tiếp theo bạn nhìn vào nó! Cụ thể, bạn không nên sửa đổi dữ liệu mà luồng UI có thể sắp sử dụng cho mục đích hiển thị. Ví dụ: nếu bạn có một thuộc tính và Personvới , và bạn đã làm:FirstNameLastName

person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";

Sau đó, UI có thể sẽ hiển thị "Keyser Spacey". (Có một cơ hội bên ngoài nó có thể hiển thị "Kevin Soze" nhưng chỉ thông qua sự kỳ lạ của mô hình bộ nhớ.)

Trừ khi bạn có loại vấn đề này, tuy nhiên, Control.BeginInvokesẽ dễ dàng hơn để xử lý đúng và sẽ tránh chủ đề nền của bạn không phải chờ đợi vì lý do chính đáng. Lưu ý rằng nhóm Windows Forms đã đảm bảo rằng bạn có thể sử dụng Control.BeginInvoketheo cách "cháy và quên" - tức là không bao giờ gọi EndInvoke. Điều này không đúng với các cuộc gọi không đồng bộ nói chung: thông thường mỗi BeginXXX nên có một cuộc gọi EndXXX tương ứng, thường là trong cuộc gọi lại.


4
Vậy thì tại sao ppl lại sử dụng Invoke over BeingInvoke? Không nên có một số lợi thế khi sử dụng Invoke. Cả hai thực hiện các quá trình trong nền, chỉ có một cái nằm trên cùng một luồng, cái còn lại trên luồng khác?
yeeen

2
@Jon: Trong khi tôi đang sử dụng Dispatcher.Begin, hãy nhập mã của tôi đang hoạt động tốt và trong Dispatcher. Nhập vào ứng dụng của tôi khiến tôi đợi trong vài giây rồi nó khởi chạy tất cả các điều khiển sau đó khởi chạy ?
SharpUrBrain

6
@SharpUrBrain: Control.BeginInvoke là loại tương đương với Dispatcher.BeginInvoke, nhưng đối với WinForms (trong khi Dispatcher dành cho WPF và Silverlight).
Jon Skeet

4
@SharpUrBrain: Tôi sẽ đề nghị bạn hỏi một câu hỏi cụ thể thay vì tiếp tục bình luận - và tất nhiên kiểm tra xem câu hỏi tương tự đã được người khác hỏi trước chưa.
Jon Skeet

2
@AZ: Có, bởi "trên luồng UI", anh ta có nghĩa là trên "luồng UI" cụ thể sở hữu tay cầm của Control đó. Thông thường, chỉ có một luồng UI, nhưng có thể có nhiều luồng UI và trong các ứng dụng nâng cao có những lý do khiến bạn muốn chúng. Về mặt kỹ thuật, bất kỳ luồng nào (bình thường?) Đều có thể khởi động bơm thông báo UI và trở thành luồng UI - và sau đó có thể tắt bơm thông báo và không còn là luồng UI. (Tuy nhiên, tôi cho rằng đó không phải là thứ gì đó để thử trên một luồng xử lý.)
Rob Parker

46

Dựa trên câu trả lời của Jon Skeet, có những lúc bạn muốn gọi một đại biểu và chờ đợi quá trình thực thi của nó hoàn thành trước khi chuỗi hiện tại tiếp tục. Trong những trường hợp đó, cuộc gọi Gọi là những gì bạn muốn.

Trong các ứng dụng đa luồng, bạn có thể không muốn một luồng chờ trên một đại biểu để hoàn thành thực thi, đặc biệt nếu đại biểu đó thực hiện I / O (có thể làm cho ủy nhiệm và khối luồng của bạn).

Trong những trường hợp đó, BeginInvoke sẽ hữu ích. Bằng cách gọi nó, bạn đang nói với đại biểu bắt đầu nhưng sau đó, chủ đề của bạn được tự do làm những việc khác song song với đại biểu.

Sử dụng BeginInvoke làm tăng độ phức tạp của mã của bạn nhưng có những lúc hiệu năng được cải thiện đáng để phức tạp.


27

Sự khác biệt giữa Control.Invoke()Control.BeginInvoke()là,

  • BeginInvoke()sẽ lên lịch cho hành động không đồng bộ trên luồng GUI. Khi hành động không đồng bộ được lên lịch, mã của bạn sẽ tiếp tục. Một thời gian sau (bạn không biết chính xác khi nào) hành động không đồng bộ của bạn sẽ được thực thi
  • Invoke() sẽ thực thi hành động không đồng bộ của bạn (trên luồng GUI) và đợi cho đến khi hành động của bạn hoàn tất.

Một kết luận hợp lý là một ủy nhiệm mà bạn vượt qua Invoke()có thể có các tham số ngoài hoặc giá trị trả về, trong khi một ủy nhiệm bạn chuyển qua BeginInvoke()không thể (bạn phải sử dụng EndInvoke để lấy kết quả).


20

Chỉ cần đưa ra một ví dụ ngắn, làm việc để thấy ảnh hưởng của sự khác biệt của họ

new Thread(foo).Start();

private void foo()
{
  this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
    (ThreadStart)delegate()
    {
        myTextBox.Text = "bing";
        Thread.Sleep(TimeSpan.FromSeconds(3));
    });
  MessageBox.Show("done");
}

Nếu sử dụng BeginInvoke , MessageBox sẽ đồng thời cập nhật văn bản. Nếu sử dụng Gọi , MessageBox sẽ bật sau khi ngủ 3 giây. Do đó, hiển thị hiệu ứng của một cuộc gọi không đồng bộ ( BeginInvoke ) và cuộc gọi ( Gọi ) đồng bộ .


9

Delegate.BeginInvoke () xếp hàng không đồng bộ cuộc gọi của đại biểu và trả lại quyền điều khiển ngay lập tức. Khi sử dụng Delegate.BeginInvoke (), bạn nên gọi Delegate.EndInvoke () trong phương thức gọi lại để nhận kết quả.

Delegate.Invoke () gọi đồng bộ đại biểu trong cùng một luồng.

Bài viết MSDN


8

Chỉ cần thêm lý do và thời điểm sử dụng Invoke ().

Cả Invoke () và BeginInvoke () sắp xếp mã bạn chỉ định cho luồng xử lý.

Nhưng không giống như BeginInvoke (), Invoke () giữ chuỗi của bạn cho đến khi bộ điều phối thực thi mã của bạn. Bạn có thể muốn sử dụng Invoke () nếu bạn cần tạm dừng một hoạt động không đồng bộ cho đến khi người dùng đã cung cấp một số loại phản hồi.

Ví dụ: bạn có thể gọi Invoke () để chạy một đoạn mã hiển thị hộp thoại OK / Hủy. Sau khi người dùng nhấp vào nút và mã sắp xếp của bạn hoàn tất, phương thức invoke () sẽ trở lại và bạn có thể hành động theo phản hồi của người dùng.

Xem Pro WPF trong C # chương 31

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.