2009-03-04 33 views
32

Tôi mới vào mô hình chuỗi trong .net. Những gì bạn sẽ sử dụng để:Quá trình không đồng bộ bắt đầu và đợi cho đến khi kết thúc

  1. bắt đầu một quá trình xử lý một tập tin (process.StartInfo.FileName = fileName;)
  2. chờ đợi cho người sử dụng để đóng tiến trình OR bỏ thread sau một thời gian
  3. nếu người dùng đóng quá trình này, xóa các tập tin

Bắt đầu quá trình này và chờ đợi nên được thực hiện trên một sợi khác với các chủ đề chính, vì hoạt động này không ảnh hưởng đến ứng dụng.

Ví dụ:

Ứng dụng của tôi tạo báo cáo html. Người dùng có thể nhấp chuột phải vào một nơi nào đó và nói "Xem Báo cáo" - bây giờ tôi truy xuất nội dung báo cáo trong một tệp tạm thời và khởi chạy quá trình xử lý tệp html tức là trình duyệt mặc định. Vấn đề là tôi không thể dọn dẹp, tức là xóa tập tin tạm thời.

+0

Giao diện điều khiển ap hoặc WinForms hoặc ASP.NET? – Richard

+0

Bàn điều khiển hoặc WinForms.Quá trình tôi bắt đầu là cục bộ cho máy. –

+0

Tôi có một ví dụ sử dụng async/await được đăng tại đây-- http://www.allampersandall.com/2013/03/net-process-async-await – Micah

Trả lời

58

"và chờ đợi phải là không đồng bộ" - Tôi không cố gắng để được hài hước, nhưng không phải là một mâu thuẫn trong điều khoản? Tuy nhiên, kể từ khi bạn đang bắt đầu một Process, sự kiện Exited có thể giúp:

ProcessStartInfo startInfo = null; 
Process process = Process.Start(startInfo); 
process.EnableRaisingEvents = true; 
process.Exited += delegate {/* clean up*/}; 

Nếu bạn muốn thực sự chờ đợi (timeout vv), sau đó:

if(process.WaitForExit(timeout)) { 
    // user exited 
} else { 
    // timeout (perhaps process.Kill();) 
} 

Đối chờ async, có lẽ chỉ cần sử dụng một chủ đề khác nhau?

ThreadPool.QueueUserWorkItem(delegate { 
    Process process = Process.Start(startInfo); 
    if(process.WaitForExit(timeout)) { 
     // user exited 
    } else { 
     // timeout 
    } 
}); 
+0

Tôi có một câu hỏi. Nếu tôi có một chức năng A() {ThreadPool.UnsafeQueueUserWorkItem ((o) => { .... proc.WaitForExit(); ... } và trong phương thức main Tôi có như thế này: Một(); Console.Write ("aa"), ví dụ ... điều là khi console.write hoàn thành công việc của nó và luồng vẫn không kết thúc công việc của nó .. trang đang tải và nó không chờ quá trình Tôi nên làm gì? Cảm ơn các bạn – Grace

+0

@Grace khó nói dựa trên điều đó ... nhưng trừ khi bạn * đợi * cho chuỗi công nhân, không phải là chính xác những gì bạn mong đợi * sẽ thấy? –

+0

vì vậy tôi nên chờ cho thread để kết thúc từ phương pháp chính? – Grace

4

Hãy thử mã sau.

public void KickOffProcess(string filePath) { 
    var proc = Process.Start(filePath); 
    ThreadPool.QueueUserWorkItem(new WaitCallBack(WaitForProc), proc); 
} 

private void WaitForProc(object obj) { 
    var proc = (Process)obj; 
    proc.WaitForExit(); 
    // Do the file deletion here 
} 
+1

Không chắc chắn nó xử lý "HOẶC bỏ qua các chủ đề sau một thời gian" –

0

Tôi có thể không sử dụng quy trình riêng để mở tệp. Thay vào đó, tôi có thể sử dụng một chủ đề nền (nếu tôi nghĩ rằng các hoạt động sẽ mất một thời gian dài và có thể chặn các chủ đề giao diện người dùng).

private delegate void FileOpenDelegate(string filename); 

public void OpenFile(string filename) 
{ 
    FileOpenDelegate fileOpenDelegate = OpenFileAsync; 
    AsyncCallback callback = AsyncCompleteMethod; 
    fileOpenDelegate.BeginInvoke(filename, callback, state); 
} 

private void OpenFileAsync(string filename) 
{ 
    // file opening code here, and then do whatever with the file 
} 

Tất nhiên, đây không phải là một ví dụ làm việc tốt (nó sẽ trả về không có gì) và tôi đã không được hiển thị như thế nào giao diện người dùng được cập nhật (bạn phải sử dụng BeginInvoke ở cấp giao diện người dùng vì một sợi nền không thể cập nhật Chuỗi giao diện người dùng). Nhưng cách tiếp cận này nói chung là làm thế nào tôi đi về xử lý các hoạt động không đồng bộ trong. Net.

+0

Xin lỗi, thực sự tôi có nghĩa là quá trình nên xử lý các tập tin, không mở nó. Tôi viết lại câu hỏi. –

0

Bạn có thể sử dụng các sự kiện Exited trong Process lớp

ProcessStartInfo info = new ProcessStartInfo(); 

info.FileName = "notepad.exe"; 
Process process = Process.Start(info); 

process.Exited += new EventHandler(process_Exited); 
Console.Read(); 

và trong trường hợp mà bạn có thể xử lý các hoạt động mà bạn đề cập

+0

tính năng này không đồng bộ –

17

Thêm một sự thay thế tiên tiến cho câu hỏi cũ này. Nếu bạn muốn chờ đợi cho một quá trình để thoát ra mà không ngăn chặn bất kỳ chủ đề và vẫn ủng hộ timeout, hãy thử như sau:

public static Task<bool> WaitForExitAsync(this Process process, TimeSpan timeout) 
    { 
     ManualResetEvent processWaitObject = new ManualResetEvent(false); 
     processWaitObject.SafeWaitHandle = new SafeWaitHandle(process.Handle, false); 

     TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); 

     RegisteredWaitHandle registeredProcessWaitHandle = null; 
     registeredProcessWaitHandle = ThreadPool.RegisterWaitForSingleObject(
      processWaitObject, 
      delegate(object state, bool timedOut) 
      { 
       if (!timedOut) 
       { 
        registeredProcessWaitHandle.Unregister(null); 
       } 

       processWaitObject.Dispose(); 
       tcs.SetResult(!timedOut); 
      }, 
      null /* state */, 
      timeout, 
      true /* executeOnlyOnce */); 

     return tcs.Task; 
    } 

Một lần nữa, lợi thế để tiếp cận này so với câu trả lời được chấp nhận là bạn không chặn bất kỳ chủ đề, giúp giảm chi phí cho ứng dụng của bạn.

Các vấn đề liên quan