2

別のスレッドからキャンセルできるようにする必要がある、実行時間の長い COM+ メソッドがあります。COM+ オブジェクトを操作するために C#/.NET を使用しています。両方の COM+ オブジェクトを「フリー」スレッド モデルを持つように構成しました。この C# サンプルは、COM+ オブジェクトの使用方法を示しています。

static void Main(string[] args)
{
    var sampleCOMClass = new SampleCOMObjectClass();
    var cancelToken = new CancelCOMObjectClass();
    try
    {
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(10));
            cancelToken.Cancel(); // this method never makes it to COM
            Console.WriteLine("Cancelled!");
        });
        sampleCOMClass.LongProcess(cancelToken);
    }
    finally
    {
        Marshal.ReleaseComObject(sampleCOMClass);
        Marshal.ReleaseComObject(cancelToken);
    }
}

私の長期実行プロセスはキャンセル トークンを正しくチェックして、処理を終了する必要があるかどうかを判断しますが、Cancelメソッドは COM+ オブジェクトに到達しません。メソッドがブロックされているかのように、LongProcess終了を待っています。「フリー」スレッド モデルにより、実装が同期を管理できると考えたため、なぜこれを行っているのかわかりません。

これは、再現する最小限の例を含む BitBucket リポジトリです。 https://bitbucket.org/theonlylawislove/so-blocking-com-call

Cancelが呼び出されない/ブロックされないのはなぜですか?

COMオブジェクトのキャンセル

STDMETHODIMP CCancelCOMObject::Cancel(void)
{
    _isCancelled = VARIANT_TRUE;
    return S_OK;
}

STDMETHODIMP CCancelCOMObject::get_IsCancelled(VARIANT_BOOL* pVal)
{
    *pVal = _isCancelled;
    return S_OK;
}

サンプルCOMオブジェクト

STDMETHODIMP CSampleCOMObject::LongProcess(ICancelCOMObject* cancel)
{
    VARIANT_BOOL isCancelled = VARIANT_FALSE;
    while(isCancelled == VARIANT_FALSE)
    {
        Sleep(1000);
        cancel->get_IsCancelled(&isCancelled);
    }
    return S_OK;
}
4

1 に答える 1