DioDocs for Excel
DioDocs for Excel
非同期関数
機能 > 数式 > 非同期関数

非同期関数とは、結果を非同期または同時に配信する関数です。 非同期関数はノンブロッキング アーキテクチャを備えているため、あるタスクの実行は別のタスクに依存しません。タスクは同時に実行できます。 非同期関数を実行すると、複数の計算を同時に実行できるため、パフォーマンスが向上します。DioDocs for Excel では、関数を AsyncCustomFunction クラスから派生することで、非同期計算を実行できます。EvaluateAsync メソッドを使用すると、関数が非同期的に計算を実行します。 また、DioDocs for Excelには、セルが非同期数式を計算していることを示す CalcError 列挙値の列挙値 Busyがあります。

カスタム非同期関数を追加して使用するには、次のサンプルコードを参照してください。

C#
コードのコピー
internal class Program
{
    static void Main(string[] args)
    {
        // Register Async custom function.
        Workbook.AddCustomFunction(new MyAddFunction());

        // Implement the Async custom Function.
        Workbook workbook = new Workbook();
        var worksheet = workbook.Worksheets[0];
        worksheet.Range["A1"].Value = 1;
        worksheet.Range["B1"].Value = 2;

        // Add the cell values.
        worksheet.Range["C1"].Formula = "=MyAdd(A1,B1)";
        var value = worksheet.Range["C1"].Value;

        // Display result. The result will be "Busy".
        Console.WriteLine($"get value first time:{value}");
        Thread.Sleep(2000);
        value = worksheet.Range["C1"].Value;

        // Display result. The result will be "3".
        Console.WriteLine($"get value second time:{value}");
    }
}
// Define Async custom function: MyAddFunction.
public sealed class MyAddFunction : AsyncCustomFunction
{
    public MyAddFunction()
        : base("MyAdd", FunctionValueType.Number, new Parameter[] { new Parameter(FunctionValueType.Number), new Parameter(FunctionValueType.Number) })
    {

    }

    async protected override Task<object> EvaluateAsync(object[] arguments, ICalcContext context)
    {
        await Task.Delay(1000);
        return (double)arguments[0] + (double)arguments[1];
    }
}

制限事項

AsyncCustomFunctionのパラメータは参照を受け入れません。これは、非同期関数は別のスレッドで実行される可能性があり、参照を使用すると複数のスレッドの競合が発生するためです。同様に、IWorksheetやIWorkbookなどのオブジェクトを非同期関数内で使用できません。

非同期IMAGE関数

DioDocs for Excelは、URLパスからセルに画像を追加できる非同期IMAGE数式関数をサポートしています。IMAGE関数は、代替テキスト、画像のサイズ、高さ、幅を設定するためのalt_text、sizing、height、widthパラメータが提供されています。この関数のsourceパラメータを使用して、画像のURLパスを「https」プロトコルで指定できます。このWebリクエストを処理するために、DioDocs for Excelは WorkbookクラスのWebRequestHandlerプロパティを提供しており、アプリケーションのWebリクエストにアクセスしてカスタマイズできます。WebRequestHandlerプロパティはIWebRequestHandlerインターフェイス型です。これは、Web リクエストを非同期に処理するためのインターフェイスを定義し、指定されたURLにGETリクエストを送信する方法を提供します。

非同期関数は結果を非同期または同時に提供しますが、一部の操作は他の関数の計算結果に依存します。DioDocs for Excelは、IWorkbookインターフェースのWaitForCalculationToFinishメソッドを提供しており、計算結果に依存する他の操作に進む前に、必要な計算がすべて実行されていることを確認できます。このメソッドは、非同期の計算を含むすべての計算が完了するまで待機します。またこのメソッドは、すべての計算が終了するまで現在のスレッドをブロックします。

非同期IMAGE関数を追加して使用するには、次のサンプルコードを参照してください。

C#
コードのコピー
static void Main(string[] args)
{
    // Set a custom web request handling class to send all network requests.
    Workbook.WebRequestHandler = new WebRequestHandler();

    // Initialize Workbook.
    var workbook = new Workbook();

    // Get the active sheet.
    var sheet = workbook.ActiveSheet;

    // Set IMAGE function.
    sheet.Range["A1:F10"].Formula = "=IMAGE(\"https://support.content.office.net/en-us/media/926439a2-bc79-4b8b-9205-60892650e5d3.jpg\", \"Pyramid\")";

    // Calculate all formulas so the asynchronous image function will run.
    workbook.Calculate();

    // Block the current thread until all asynchronous functions have finished to avoid #BUSY! error in the exported file.
    workbook.WaitForCalculationToFinish();

    // Save the workbook.
    workbook.Save("AsyncImageFunction.pdf");
    workbook.Save("AsyncImageFunction.xlsx");
}

// Create custom web request handling class.
public class WebRequestHandler : IWebRequestHandler
{
    public async Task<WebRequestResult> GetAsync(string requestUri)
    {
        var result = new WebRequestResult();
        using (HttpClient? client = new HttpClient())
        {
            try
            {
                HttpResponseMessage? response = await client.GetAsync(requestUri);
                result.StatusCode = (int)response.StatusCode;
                if (response.IsSuccessStatusCode)
                {
                    result.ResponseContent = await response.Content.ReadAsByteArrayAsync();
                }
            }
            catch (HttpRequestException)
            {
                result.IsConnectionFailed = true;
            }
        }
        return result;
    }
}