簡體   English   中英

C#如何取消一個正在執行的方法

[英]C# how cancel an executing method

我有一個委托方法可以在我的應用程序中運行一個繁重的進程(我必須使用 MS Framework 3.5):

private delegate void delRunJob(string strBox, string strJob);

執行:

    private void run()
    {
        string strBox = "G4P";
        string strJob = "Test";

        delRunJob delegateRunJob = new delRunJob(runJobThread);
        delegateRunJob.Invoke(strBox, strJob);
    }

runJobThread方法的某些部分

我調用外部程序(SAP - 遠程函數調用)來檢索數據。 該行的執行可能需要 1-30 分鍾。

private void runJobThread(string strBox, string strJob)
{
    // CODE ...
    sapLocFunction.Call(); // When this line is running I cannot cancel the process
    // CODE ...
}

我想允許用戶取消整個過程。

怎樣才能做到這一點? 我嘗試了一些方法; 但我屬於同一點; 當這條特定線路正在運行時,我無法停止該過程。

您必須研究異步和等待機制,而不是使用委托機制。 當您了解此機制后,您可以轉到取消令牌。 可以在此處找到同時執行這兩種操作的示例: http : //blogs.msdn.com/b/dotnet/archive/2012/06/06/async-in-4-5-enabling-progress-and-cancellation-in-異步apis.aspx

好; 我找到了一種復雜但有效的方法來解決我的問題:

a.) 我創建了一個“Helper application”來在進程運行時顯示一個通知圖標(以確保不干擾主應用程序的正常執行):

private void callHelper(bool blnClose = false)
{
    if (blnClose)
        fw.processKill("SDM Helper");
    else
        Process.Start(fw.appGetPath + "SDM Helper.exe");
}

b.) 我創建了一個只調用重進程行的線程。

c.) 當線程處於活動狀態時,我會檢查名為“cancel”的外部文件(“Helper 應用程序”執行此操作;當用戶單擊選項以取消 Helper 創建文件的過程時)。

d.) 如果文件存在; 處理所有對象並打破 while 循環。

e.) sapLocFunction.Call()方法將引發異常,但我預計會出現錯誤。

private void runJobThread(string strBox, string strJob)
{
    // CODE ...

    Thread thrSapCall = new Thread(() =>
    {
        try { sapLocFunction.Call(); }
        catch { /* Do nothing */ }
    });

    thrSapCall.Start();

    while (thrSapCall.IsAlive)
    {
        Thread.Sleep(1000);
        try
        {
            if (fw.fileExists(fw.appGetPath + "\\cancel"))
            {
                sapLocFunction = null;
                sapLocTable = null;
                sapConn.Logoff();
                sapConn = null;
                canceled = true;
                break;
            }
        }
        finally { /* Do nothing */ }
    }

    thrSapCall = null;

    // CODE ...
}

奇跡般有效!

我認為您將不得不求助於此處描述的方法。 閱讀這篇文章,了解為什么這離理想還有很長的路要走。 也許這可能有效......

private void runJobThread(string strBox, string strJob, CancellationToken token)
{
   Thread t = Thread.CurrentThread;
    using (token.Register(t.Abort))
    {
    // CODE ...
    sapLocFunction.Call(); // When this line is running I cannot cancel the process
    // CODE ...
   } 
}

一些dnspynco3.0 上公開了一個取消方法。

    private readonly static Type RfcConnection = typeof(RfcSessionManager).Assembly.GetType("SAP.Middleware.Connector.RfcConnection");
    
    private readonly static Func<RfcDestination, object> GetConnection = typeof(RfcSessionManager).GetMethod("GetConnection", BindingFlags.Static | BindingFlags.NonPublic).CreateDelegate(typeof(Func<RfcDestination, object>)) as Func<RfcDestination, object>;
    
    private readonly static MethodInfo Cancel = RfcConnection.GetMethod("Cancel", BindingFlags.Instance | BindingFlags.NonPublic);


    object connection = null;
    var completed = true;
    
    using (var task = Task.Run(() => { connection = GetConnection(destination); rfcFunction.Invoke(destination); }))
{  
    try
    {
         completed = task.Wait(TimeSpan.FromSeconds(invokeTimeout));
    
         if (!completed)
             Cancel.Invoke(connection, null);                            
                                
         task.Wait();
    }
    catch(AggregateException e)
    {
         if (e.InnerException is RfcCommunicationCanceledException && !completed)
             throw new TimeoutException($"SAP FM {functionName} on {destination} did not respond in {timeout} seconds.");
         throw;
    }   
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM