我会创建一个单独的应用程序域来运行一个不受信任的程序集,或者就像你的情况那样不时工作。应用程序域可以随时卸载,它将在您的代码和外部代码之间创建一个边界。这是一个小例子。让我们先从包含不正确的代码外部组件:
public class Processor
{
public void Run()
{
while (true) { /* ... */ }
}
}
现在,我们需要一个类,将加载BadAssembly.dll,创建处理器的一个实例,并调用运行方法在单独的线程中为了不阻止你的应用程序的主线程。
public class Loader : MarshalByRefObject
{
public bool IsCompleted { get; private set; }
public bool IsFaulted { get; private set; }
public void LoadAndRunBadAssembly()
{
var ass = Assembly.LoadFrom("BadAssembly.dll");
var c = (Processor)ass.CreateInstance("BadAssembly.Processor");
Task.Factory.StartNew(() =>
{
try
{
c.Run();
IsCompleted = true;
}
catch (Exception)
{
IsFaulted = true;
}
}, TaskCreationOptions.LongRunning);
}
}
IsCompleted和IsFaulted性需要,让我们知道,如果外部的代码已经处理完毕或没有。 加载程序从MarshalByRefObject派生,因为它的代码将在我们创建的独立域中执行。这里是一个代码来测试装载机类:
var appDomain = AppDomain.CreateDomain("Loader");
try
{
//Here I assume that Loader class is in the same assembly as this code
var loader = (Loader)appDomain.CreateInstanceAndUnwrap(
Assembly.GetExecutingAssembly().FullName,
typeof (Loader).FullName);
loader.LoadAndRunBadAssembly();
Console.WriteLine("Waiting...");
Thread.Sleep(20000); //This simulates waiting for external code
if (loader.IsCompleted)
Console.WriteLine("Processing has finished");
else if (loader.IsFaulted)
Console.WriteLine("There was an error");
else
Console.WriteLine("It lasts too long");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
AppDomain.Unload(appDomain);
}
UPDATE
我刚刚意识到,为了停止线程在一个域中AppDomain.Unload方法使用中止方法。这意味着您在尝试卸载域时可能会收到CannotUnloadAppDomainException异常。它会发生,因为不能保证中止会立即杀死一个线程。
你如何从这个库调用代码?你是否明确地创建了一个新的线程,如果是的话,怎么样?一段代码将会很有用。 – 2014-11-08 14:30:35
这是不可能的,只是杀死线程。唯一可以安全杀死的就是整个过程。 '线程。Abort'只会在线程执行托管代码时工作,所以对于本地的第三方库来说,这无济于事。因此,将违规代码分离成一个新的简单流程,您可以从您的应用程序运行并在需要时终止。 – Luaan 2014-11-08 15:09:18