2013-08-22 41 views
19

Tôi cực kỳ mới để lập trình, và tôi đã học đủ tốt cho đến nay, tôi nghĩ, nhưng tôi vẫn không thể nắm bắt được ý tưởng làm chậm trễ theo cách tôi muốn. Những gì tôi đang làm là một loại thử nghiệm "trò chơi" thingy bằng cách sử dụng một ứng dụng Windows hình thức liên quan đến một hệ thống chiến đấu. Trong đó, tôi muốn tạo một NPC thực hiện một hành động sau mỗi vài giây. Vấn đề là, tôi cũng muốn cho phép người chơi tương tác giữa các đòn tấn công. Thread.sleep thực sự dường như không làm việc cho tôi không chỉ vì tôi không biết làm thế nào để đa luồng, nhưng bất cứ khi nào tôi cố gắng để chạy nó, nói, như thế này:Làm cách nào để thực hiện một sự chậm trễ ngắn trong C# mà không cần sử dụng chế độ ngủ?

textBox1.Text += "\r\nThread Sleeps!"; 
System.Threading.Thread.Sleep(4000); 
textBox1.Text += "\r\nThread awakens!"; 

Dường như nhấn mạnh vào ngủ đầu tiên, sau đó in cả hai dòng.

Tôi nghĩ rằng đó là tất cả những gì tôi có thể nói vào lúc này, nhưng nếu điều đó vẫn còn quá mơ hồ hoặc dài dòng, hãy cho tôi biết.

Tóm lại, Trong C# tôi muốn thực hiện một sự chậm trễ trước khi chạy nhưng đồng thời vẫn cho phép tương tác người dùng.

+1

bạn có thể sử dụng bộ đếm thời gian để thay thế và cháy nó tại khoảng thời gian của bạn ... – Rohit

+0

Chủ đề cũng chịu trách nhiệm in giao diện người dùng của bạn, nhưng vì bạn chặn nó bằng cách sử dụng 'Ngủ ', nó không thể cập nhật giao diện người dùng hiển thị dòng đầu tiên của bạn. – user2674389

+0

Sử dụng Task.Delay thay vì Sleep. Sau đó, bạn sẽ không gặp bất kỳ sự cố nào với giao diện người dùng bị chặn. Chức năng mới này có sẵn trong .Net 4.5. – Ohlin

Trả lời

47

Nếu bạn đang sử dụng .NET 4.5, bạn có thể sử dụng khung công tác async/await mới để ngủ mà không khóa chuỗi.

Cách hoạt động là bạn đánh dấu chức năng cần các thao tác không đồng bộ, với từ khóa async. Đây chỉ là một gợi ý cho trình biên dịch. Sau đó, bạn sử dụng từ khóa await trên dòng nơi bạn muốn mã của mình chạy không đồng bộ và chương trình của bạn sẽ đợi mà không khóa chuỗi hoặc giao diện người dùng. Phương thức bạn gọi (trên đường chờ) cũng phải được đánh dấu bằng một từ khóa async và thường được đặt tên kết thúc bằng Async, như trong ImportFilesAsync.

Những gì bạn cần làm trong ví dụ của bạn là:

  1. Hãy chắc chắn rằng chương trình của bạn có .Net Framework 4.5 như Target Framework
  2. Đánh dấu chức năng của bạn mà cần phải ngủ với từ khóa async (xem ví dụ bên dưới)
  3. Thêm using System.Threading.Tasks; vào mã của bạn.

Mã của bạn đã sẵn sàng để sử dụng phương pháp Task.Delay thay vì phương pháp System.Threading.Thread.Sleep (nó có thể sử dụng await trên Task.DelayTask.Delay được đánh dấu bằng async trong định nghĩa của nó).

private async void button1_Click(object sender, EventArgs e) 
    { 
     textBox1.Text += "\r\nThread Sleeps!"; 
     await Task.Delay(3000); 
     textBox1.Text += "\r\nThread awakens!"; 
    } 

Tại đây bạn có thể đọc thêm về Task.DelayAwait.

+0

Có đúng là tất cả các mã sau khi «đang chờ' sẽ chạy không đồng bộ? Tôi đã làm một ví dụ với hai hộp kiểm và có vẻ như vậy. – Black

+0

@Black Bạn chỉ có thể sử dụng 'await' trên một hàm được đánh dấu là 'async', vì vậy có - nó sẽ luôn không đồng bộ. – Ohlin

+0

nhưng chỉ một phần sau khi chờ đợi? – Black

1

Bạn có thể sử dụng tính giờ: http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx

Timers có thể cung cấp cho bạn một độ chính xác lên đến 1 mili giây. Tùy thuộc vào khoảng thời gian đánh dấu sự kiện sẽ được tạo ra. Làm công cụ của bạn bên trong sự kiện đánh dấu.

4

Xin lỗi vì đã đánh thức một câu hỏi cũ như thế này. Nhưng tôi nghĩ tác giả ban đầu muốn câu trả lời là gì:

Bạn cần buộc chương trình cập nhật đồ họa sau khi bạn thực hiện thay đổi đối với hộp văn bản1.Bạn có thể làm điều đó bằng cách gọi Update();

textBox1.Text += "\r\nThread Sleeps!"; 
textBox1.Update(); 
System.Threading.Thread.Sleep(4000); 
textBox1.Text += "\r\nThread awakens!"; 
textBox1.Update(); 

Thông thường việc này sẽ được thực hiện tự động khi hoàn thành chuỗi. Ví dụ, bạn nhấn một nút, các thay đổi được thực hiện cho văn bản, chuỗi chết và sau đó .Update() được kích hoạt và bạn sẽ thấy các thay đổi. (Tôi không phải là một chuyên gia vì vậy tôi không thể thực sự cho bạn biết khi nó bị sa thải, nhưng một cái gì đó tương tự như thế này.)

Trong trường hợp này, bạn thay đổi, tạm dừng chủ đề, và sau đó thay đổi văn bản một lần nữa, và khi chủ đề cuối cùng chết, .Update() được kích hoạt. Điều này dẫn đến bạn chỉ thấy thay đổi cuối cùng được thực hiện cho văn bản.

Bạn sẽ gặp phải sự cố tương tự nếu bạn có thời gian thực hiện dài giữa các thay đổi văn bản.

0
private void WaitNSeconds(int seconds) 
{ 
    if (seconds < 1) return; 
    DateTime _desired = DateTime.Now.AddSeconds(seconds); 
    while (DateTime.Now < _desired) { 
     Thread.Sleep(1); 
     System.Windows.Forms.Application.DoEvents(); 
    } 
} 
0

Bằng cách thêm using System.Timers; để chương trình của bạn, bạn có thể sử dụng chức năng này:

private static void delay(int Time_delay) 
{ 
    int i=0; 
    // ameTir = new System.Timers.Timer(); 
    _delayTimer = new System.Timers.Timer(); 
    _delayTimer.Interval = Time_delay; 
    _delayTimer.AutoReset = false; //so that it only calls the method once 
    _delayTimer.Elapsed += (s, args) => i = 1; 
    _delayTimer.Start(); 
    while (i == 0) { }; 
} 

trễ là một chức năng và có thể được sử dụng như:

delay(5000); 
Các vấn đề liên quan