2011-06-20 35 views
6

Bất kỳ ai cũng có thể đề xuất Mẫu thiết kế tốt để báo cáo/theo dõi trạng thái/tiến trình của các quy trình dài. Về cơ bản, tôi có một codebase mà nhận được một "dữ liệu ngữ cảnh" đối tượng:Mẫu thiết kế để báo cáo/giám sát tiến trình của các quy trình dài

public class DataContext : IDataContext 
{ 
    pulbic Dictionary<string, objects> Properties { get; private set; } 

    // Additional properties removed for simplicity... 
} 

Dựa trên bối cảnh cung cấp, một đối tượng Task (không TPL-Task) được tạo ra, với nhiệm vụ nhỏ khác nhau. Trong khi thực hiện, đối tượng DataContext được chuyển đến các nhiệm vụ phụ khác nhau, có thể truy xuất hoặc cập nhật nó.

Ví dụ: giả sử tác vụ chính là tác vụ "Sao chép tệp". DataContext sẽ có các thuộc tính như SourceFolder và TargetFolder, và có lẽ thuộc tính FilterFiles (ví dụ: * .docx). Nhiệm vụ chính của chúng tôi sẽ là một CopyFilesTasks, và nó sẽ có một "đường ống" của các nhiệm vụ phụ - Thư mục Quét, Tập tin Quét, Tập tin Lọc, Sao chép các tập tin, vv ....

Điều tôi đang tìm kiếm, là cách tốt nhất để cho phép tác vụ/nhiệm vụ phụ báo cáo tiến độ của họ cho người gọi/người thực hiện. Trong ví dụ trên của chúng tôi, những thay đổi trong tiến trình có thể chỉ là "Tệp được sao chép ABC.docx ..." hoặc có thể là một cái gì đó "phức tạp" hơn, như "Quét thư mục XYZ ..."

Tôi đã xem xét các tùy chọn sau:

  1. INotifyPropertyChanged: thêm một "Progress" tài sản để DataContext

    public string Progress {get; đặt {_progress = value; RaisePropertyChanged ("Tiến trình"); }

    và có mã tạo đối tượng DataContext đăng ký sự kiện PropertyChanged. Tuy nhiên, điều này có vẻ như một cách tiếp cận quá đơn giản ...

  2. ILog (sử dụng bất kỳ khung khai thác gỗ nào bạn thích): sử dụng một cá thể ILog trong các nhiệm vụ/nhiệm vụ phụ khác nhau và có trình xử lý tác vụ chính thêm trình nghe riêng của nó vào khung ghi nhật ký. Tuy nhiên điều này có vẻ như uốn cơ chế khai thác gỗ để làm những việc mà nó không phải làm.

  3. Udi Dahan của DomainEvents: Các đao phủ của nhiệm vụ có thể coi DataContext như một "miền", và do đó chúng ta có thể cố gắng thực hiện một "EventHandler" cho một sự kiện "ProgressChanged". Về lý thuyết, điều này có thể được sử dụng cho các sự kiện thậm chí tinh tế hơn, điều đó xảy ra trong tiểu nhiệm vụ cụ thể ... Nhưng một lần nữa, nó cảm thấy như buộc các khái niệm ...

mối quan tâm của tôi bao gồm những thứ như:

  • Tiến trình có thể không phải là "sự kiện duy nhất" cần được theo dõi - trong ví dụ trên, chúng tôi có thể muốn mọi thứ được xác định rõ ràng hơn như FolderHandled, FileCopied, v.v. các nhiệm vụ (hãy nhớ - các nhiệm vụ phụ được tạo dựa trên DataContext và có thể dẫn đến các nhiệm vụ khác nhau đang được thực hiện).
  • Ngữ cảnh chạy các tác vụ chưa được xác định. Bây giờ, tôi chỉ đang lên kế hoạch để chạy các tác vụ từ ứng dụng dòng lệnh, vì vậy việc xuất ra dòng lệnh là cần thiết để gỡ lỗi. Sau này, khi tôi chuyển dịch vụ này sang dịch vụ, tôi có thể muốn có một "người nghe" cập nhật cơ sở dữ liệu với tiến trình của công việc (ví dụ).

Trả lời

0

Xem xét BackgroundWorkers. http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx Họ có sự kiện báo cáo riêng của họ trên một chuỗi giao diện người dùng riêng biệt.

+0

Đây không phải là những gì tôi cần - Tôi không gặp vấn đề khi chạy mã trong chủ đề nền ... Tôi đang tìm giải pháp "hoàn chỉnh" hơn chứ không chỉ cách cập nhật thanh tiến trình trong UI (BTW, tôi thậm chí không có giao diện người dùng tại thời điểm này và có thể sẽ không bao giờ) – SaguiItay

1

Bạn có thể khai báo các tham số cho từng loại hoạt động tốt, nói FileOperationEventArgs cho hoạt động tập tin, DatabaseUpdateEventArgs cho hoạt động cơ sở dữ liệu, vv

public class FileOperationEventArgs : EventArgs 
{ 
    public readonly string SourceFolder; 
    public readonly string TargetFolder; 

    public FileOperationEventArgs(string sourceFolder, string targetFolder) 
    { 
     SourceFolder = sourceFolder; 
     TargetFolder = targetFolder; 
    } 
} 

public class DatabaseUpdateEventArgs : EventArgs 
{ 
    public readonly int RowsUpdated; 

    public DatabaseUpdateEventArgs(int rowsUpdated) 
    { 
     RowsUpdated = rowsUpdated; 
    } 
} 

lớp OperationProgress tuyên bố sự kiện đối với từng loại hoạt động.

public class OperationProgress 
{ 
    public event EventHandler<FileOperationEventArgs> FileCopied; 
    public event EventHandler<DatabaseUpdateEventArgs> DatabaseUpdated; 

    public void OnFileCopied(FileOperationEventArgs a) 
    { 
     if(FileCopied != null) 
      FileCopied(this, a); 
    } 

    public void OnDatabaseUpdated(DatabaseUpdateEventArgs a) 
    { 
     if (DatabaseUpdated != null) 
      DatabaseUpdated(this, a); 
    } 
} 

OperationProgress sẽ được chỉ định khi DataContext được tạo.

public class DataContext : IDataContext 
{ 
    public Dictionary<string, object> Properties { get; private set; } 
    public OperationProgress Progress { get; private set; } 

    public DataContext(OperationProgress progress) 
    { 
     Progress = progress; 
    } 
} 

Thực hiện nhiệm vụ phụ có thể cập nhật tiến trình.

public class FileCopySubTask 
{ 
    public void Execute(DataContext context) 
    { 
     context.Progress.OnFileCopied(new FileOperationEventArgs("c:/temp1", "c:/temp2")); 
    } 
} 
+0

Điều này tương tự với DomainEvents của Udi Dahan, nhưng bị hạn chế hơn - nó giới hạn sự kiện chỉ dành cho các sự kiện "đã biết" cụ thể - Tôi sẽ phải biên dịch mọi thứ trong trường hợp có nhiệm vụ mới với sự kiện mới ... nó cũng có nghĩa là tôi sẽ phải quản lý sự kiện đăng ký/hủy đăng ký và tham chiếu nếu tôi có nhiều tác vụ và nhiều "người nghe" ... – SaguiItay

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