Các tệp Microsoft Project MPP và Primavera XER có thể mất từ vài giây đến vài phút để phân tích. Khi quá trình này đang chạy, một ứng dụng đơn giản trông như bị treo: không có thanh tiến trình, không có văn bản trạng thái, không có gì người dùng có thể thao tác. Bất kỳ ai tải các lịch trình lớn đều cần một cách để hiển thị mức độ tiến độ của quá trình tải, và một cách để dừng lại nếu nó chạy quá lâu.

Hướng dẫn này bao gồm cả Aspose.Tasks for .NET. Bạn sẽ xây dựng một callback tiến độ báo cáo giai đoạn hiện tại và phần trăm, tích hợp nó vào quá trình tải, giữ cho giao diện người dùng trên desktop phản hồi nhanh trong khi việc phân tích chạy trên một luồng nền, và hủy tải nếu vượt quá ngân sách thời gian.

Các điểm quan trọng

  • IProgressNotificationCallback.Notify(ProgressNotificationArgs) là phương thức duy nhất bạn triển khai để nhận tiến độ tải từ Aspose.Tasks for .NET.
  • ProgressNotificationArgs cung cấp CurrentStepName, CurrentStepProgress (0–100), và EstimatedTotalProgress (0–100).
  • Gắn callback bằng LoadOptions.ProjectLoadingCallback; nó hỗ trợ các định dạng MPP và XER.
  • Notify chạy trên luồng tải, vì vậy cần chuyển các giá trị sang luồng UI trước khi cập nhật điều khiển.
  • Hủy tải chậm bằng cách đặt LoadOptions.CancellationToken và gọi Cancel() trên CancellationTokenSource của nó từ một luồng khác.
  • API tiến độ hoạt động ở chế độ đánh giá; giấy phép chỉ loại bỏ giới hạn kích thước tệp và giới hạn đầu ra.

Mới sử dụng thư viện? trang sản phẩm Aspose.Tasks for .NETtài liệu cung cấp đầy đủ hướng dẫn cài đặt và cấp phép.

Cách Giám sát Tiến độ Tải Dự án trong C#?

Triển khai IProgressNotificationCallback, đặt nó vào LoadOptions.ProjectLoadingCallback, và tải tệp thông qua hàm tạo Project chấp nhận LoadOptions. Mã làm việc tối thiểu bao gồm ba phần: một lớp callback, một thể hiện LoadOptions, và lời gọi tải.

  • Input: một tệp MPP hoặc XER, ví dụ BigProject.mpp
  • Output: các cập nhật tiến độ trong quá trình phân tích — CurrentStepName, CurrentStepProgress, EstimatedTotalProgress
  • Library: Aspose.Tasks for .NET
  • Language: C#
using System;
using Aspose.Tasks;

internal sealed class ConsoleProgressCallback : IProgressNotificationCallback
{
    public void Notify(ProgressNotificationArgs args)
    {
        Console.WriteLine(
            "{0}: step {1}% / total {2}%",
            args.CurrentStepName,
            args.CurrentStepProgress,
            args.EstimatedTotalProgress);
    }
}

internal static class Program
{
    private static void Main()
    {
        // A license is optional here. Uncomment to remove evaluation limits.
        // new License().SetLicense("Aspose.Tasks.lic");

var loadOptions = new LoadOptions
        {
            ProjectLoadingCallback = new ConsoleProgressCallback()
        };

var project = new Project("BigProject.mpp", loadOptions);

Console.WriteLine("Loaded {0} top-level tasks.", project.RootTask.Children.Count);
    }
}

Khi tệp được phân tích, Notify chạy nhiều lần và console hiển thị giai đoạn và phần trăm. Sau khi hàm khởi tạo trả về, đối tượng Project đã được tải đầy đủ và có thể sử dụng.

Tại sao việc giám sát tiến độ tải lên lại quan trọng đối với các tệp lớn?

Nó thay thế khoảng dừng trông như không phản hồi bằng phản hồi có thể nhìn thấy, đó là sự khác biệt giữa một ứng dụng trông bị hỏng và một ứng dụng trông đang bận. Tập tin càng lớn, quá trình phân tích càng lâu, và việc tải ẩn gây mất chất lượng cảm nhận càng nhiều.

Các cách sử dụng cụ thể cho các giá trị tiến trình:

  • Điều khiển thanh tiến trình xác định từ EstimatedTotalProgress thay vì hiển thị spinner vô hạn.
  • Ghi lại các chuyển đổi CurrentStepName để tìm giai đoạn nào chiếm phần lớn thời gian tải khi bạn phân tích một tệp chậm.
  • Giữ UI phản hồi bằng cách tải trên một luồng nền và đăng tiến độ lên luồng UI.
  • Hiển thị tiến độ từng tệp trong công cụ batch chuyển đổi hoặc di chuyển nhiều dự án theo thứ tự.

Cách Cài Đặt Aspose.Tasks và Thiết Lập Dự Án

Thêm gói Aspose.Tasks NuGet vào dự án .NET 6 hoặc mới hơn.

dotnet add package Aspose.Tasks

Hoặc, từ Console Trình quản lý gói của Visual Studio:

Install-Package Aspose.Tasks

Tiến trình callback hoạt động mà không cần giấy phép. Nếu bạn cần tải các tệp vượt quá giới hạn kích thước đánh giá hoặc xử lý mà không có các hạn chế đánh giá, hãy đặt giấy phép một lần khi khởi động:

using Aspose.Tasks;

var license = new License();
license.SetLicense("Aspose.Tasks.lic");

Bạn có thể yêu cầu một giấy phép tạm thời miễn phí từ trang giấy phép tạm thời của Aspose, và đọc thêm về thư viện trên trang sản phẩm Aspose.Tasks for .NET.

API IProgressNotificationCallback cung cấp gì?

API là một giao diện, một phương thức và một kiểu đối số, tất cả đều nằm trong không gian tên Aspose.Tasks.

Thành viênKiểuMô tả
IProgressNotificationCallback.Notify(ProgressNotificationArgs)voidĐược gọi trong quá trình thực hiện các thao tác dự án kéo dài để báo cáo tiến độ.
ProgressNotificationArgs.CurrentStepNamestring (get)Tên của giai đoạn hiện tại của thao tác.
ProgressNotificationArgs.CurrentStepProgressint (get)Phần trăm hoàn thành ước tính cho giai đoạn hiện tại, 0–100.
ProgressNotificationArgs.EstimatedTotalProgressint (get)Phần trăm hoàn thành ước tính cho toàn bộ thao tác, 0–100.
LoadOptions.ProjectLoadingCallbackIProgressNotificationCallback (get/set)Callback được gọi trong quá trình tải. Hỗ trợ cho MPP và XER.
LoadOptions.CancellationTokenSystem.Threading.CancellationToken (get/set)Token được sử dụng để hủy quá trình tải đang diễn ra.

ProgressNotificationArgs là lớp sealed và kế thừa từ EventArgs. Ba thuộc tính của nó đều chỉ đọc.

Làm thế nào để triển khai Callback thông báo tiến độ?

Tạo một lớp triển khai IProgressNotificationCallback và thực hiện một việc hữu ích với ProgressNotificationArgs trong Notify. Giữ cho phương thức nhanh, vì nó chạy trên luồng tải.

using System;
using Aspose.Tasks;

internal sealed class ConsoleProgressCallback : IProgressNotificationCallback
{
    private int lastTotal = -1;

public void Notify(ProgressNotificationArgs args)
    {
        // Only redraw when the total percentage actually changes.
        if (args.EstimatedTotalProgress == lastTotal)
        {
            return;
        }

lastTotal = args.EstimatedTotalProgress;
        Console.WriteLine("[{0,3}%] {1}", args.EstimatedTotalProgress, args.CurrentStepName);
    }
}

Cơ chế bảo vệ trên lastTotal ngăn việc làm ngập console bằng các dòng trùng lặp khi nhiều lời gọi Notify báo cáo cùng một tổng.

Làm thế nào để tải một dự án với việc theo dõi tiến độ?

Đặt ProjectLoadingCallback trên một đối tượng LoadOptions, sau đó truyền nó vào hàm tạo Project. Quá trình tải chạy đồng bộ; khi hàm tạo trả về, việc phân tích đã hoàn tất.

using System;
using Aspose.Tasks;

internal static class Loader
{
    public static Project Load(string path)
    {
        var loadOptions = new LoadOptions
        {
            ProjectLoadingCallback = new ConsoleProgressCallback()
        };

// Same call for MPP and XER; only the file path changes.
        var project = new Project(path, loadOptions);

Console.WriteLine("Done. Root task children: {0}", project.RootTask.Children.Count);
        return project;
    }
}

Bạn đang thử điều này theo lịch của riêng mình? Tải xuống giấy phép tạm thời miễn phí để chạy tải mà không bị giới hạn đánh giá về kích thước tệp.

Làm thế nào để giữ cho UI phản hồi nhanh khi đang tải?

Tải trên một luồng nền và chuyển các giá trị tiến độ sang luồng UI bên trong callback, vì Notify chạy trên bất kỳ luồng nào đã gọi hàm khởi tạo Project.

using System.Windows.Forms;
using Aspose.Tasks;

internal sealed class ProgressBarCallback : IProgressNotificationCallback
{
    private readonly ProgressBar bar;

public ProgressBarCallback(ProgressBar bar) => this.bar = bar;

public void Notify(ProgressNotificationArgs args)
    {
        if (bar.InvokeRequired)
        {
            bar.BeginInvoke(() => bar.Value = args.EstimatedTotalProgress);
        }
        else
        {
            bar.Value = args.EstimatedTotalProgress;
        }
    }
}

Trong WPF, hãy sử dụng Dispatcher.Invoke hoặc Dispatcher.BeginInvoke thay cho Control.BeginInvoke.

Làm thế nào để hủy một tải chạy lâu?

Set LoadOptions.CancellationToken thành một token từ CancellationTokenSource, sau đó gọi Cancel() trên nguồn đó từ một luồng khác. Aspose.Tasks dừng việc phân tích và hàm khởi tạo Project ném ra ngoại lệ, vì vậy hãy bọc nó trong try/catch.

using System;
using System.Threading;
using Aspose.Tasks;

var cts = new CancellationTokenSource();

var loadOptions = new LoadOptions
{
    ProjectLoadingCallback = new ConsoleProgressCallback(),
    CancellationToken = cts.Token
};

// Wire a Cancel button or a timeout to this:
// cts.CancelAfter(TimeSpan.FromSeconds(30));

try
{
    var project = new Project("BigProject.xer", loadOptions);
    Console.WriteLine("Loaded {0} tasks.", project.RootTask.Children.Count);
}
catch (Exception ex)
{
    Console.WriteLine("Load stopped: {0}", ex.Message);
}

Kết luận

Thêm tiến độ tải vào một ứng dụng Aspose.Tasks for .NET là một thay đổi nhỏ nhưng có ảnh hưởng lớn đến cảm giác phản hồi. Triển khai IProgressNotificationCallback, gán nó cho LoadOptions.ProjectLoadingCallback, và đọc CurrentStepName, CurrentStepProgressEstimatedTotalProgress trong Notify. Thêm một CancellationToken khi quá trình tải có thể kéo dài đủ lâu khiến người dùng muốn dừng chúng.

Khám phá tài liệu Aspose.Tasks for .NETtham chiếu API để đi sâu hơn, và tải xuống giấy phép tạm thời miễn phí để đánh giá không giới hạn.

Câu hỏi thường gặp

Tôi có cần giấy phép trả phí để sử dụng API thông báo tiến độ không? Không. IProgressNotificationCallback hoạt động ở chế độ đánh giá. Giấy phép tạm thời hoặc trả phí chỉ loại bỏ các giới hạn đánh giá về kích thước tệp và đầu ra; nó không mở khóa API tiến độ.

Liệu cùng một callback có hoạt động cho các tệp XER cũng như MPP không? Có. LoadOptions.ProjectLoadingCallback hiện đang được hỗ trợ cho các định dạng MPP và XER. Cùng một triển khai IProgressNotificationCallback xử lý cả hai.

Callback tiến trình có an toàn với đa luồng không? Notify được gọi trên luồng thực hiện tải, không phải luồng nền. Trong một ứng dụng desktop, hãy chuyển các giá trị sang luồng UI bằng Control.Invoke hoặc Dispatcher.Invoke trước khi thao tác với thanh tiến trình.

Sự khác nhau giữa CurrentStepProgress và EstimatedTotalProgress là gì? CurrentStepProgress là phần trăm hoàn thành cho giai đoạn hiện tại của quá trình tải, chẳng hạn như đọc nhiệm vụ hoặc đọc tài nguyên. EstimatedTotalProgress là phần trăm hoàn thành ước tính cho toàn bộ hoạt động. Cả hai đều là các số nguyên từ 0 đến 100.

Có thể hủy quá trình tải từ bên trong callback không?
Không thể từ bên trong Notify trực tiếp. Thay vào đó, đặt LoadOptions.CancellationToken thành một token từ CancellationTokenSource và gọi Cancel() trên nguồn đó từ một luồng khác. Khi đó, hàm tạo Project sẽ dừng và ném ngoại lệ, vì vậy hãy bao quanh nó bằng try/catch.

Thêm callback có làm chậm quá trình tải không?
Chi phí của callback là không đáng kể vì Notify chỉ được gọi ở một số điểm kiểm tra nhỏ, không phải cho mỗi bản ghi. Tuy nhiên, hãy giữ cho phương thức nhẹ, vì bất kỳ công việc nào bạn thực hiện bên trong nó sẽ chạy trên luồng tải.

Đọc thêm