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 ...
}
我想让用户取消整个过程。
如何实现?我尝试了一些方法;但我也陷入了同样的境地;当此特定行是 运行ning 时,我无法停止该过程。
我认为您必须求助于 described here 方法。阅读 post 了解为什么这与理想相去甚远。
也许这可能有用...
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 ...
}
}
你必须研究异步和等待机制,而不是使用委托机制。当您了解此机制后,您可以转到 cancellationtoken。
可以在此处找到执行这两项操作的示例:
http://blogs.msdn.com/b/dotnet/archive/2012/06/06/async-in-4-5-enabling-progress-and-cancellation-in-async-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 application" 执行此操作;当用户单击一个选项以取消帮助程序创建文件的过程时) .
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 ...
}
很有魅力!
一点dnspy暴露了nco3.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;
}
}
我有一个委托方法来 运行 我的应用程序中的一个繁重的进程(我必须使用 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 ...
}
我想让用户取消整个过程。
如何实现?我尝试了一些方法;但我也陷入了同样的境地;当此特定行是 运行ning 时,我无法停止该过程。
我认为您必须求助于 described here 方法。阅读 post 了解为什么这与理想相去甚远。 也许这可能有用...
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 ...
}
}
你必须研究异步和等待机制,而不是使用委托机制。当您了解此机制后,您可以转到 cancellationtoken。 可以在此处找到执行这两项操作的示例: http://blogs.msdn.com/b/dotnet/archive/2012/06/06/async-in-4-5-enabling-progress-and-cancellation-in-async-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 application" 执行此操作;当用户单击一个选项以取消帮助程序创建文件的过程时) .
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 ...
}
很有魅力!
一点dnspy暴露了nco3.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;
}
}