互联网上的所有文章都说使用Thread.Abort
是邪恶的(因为同步原语属于操作系统,并且进程尚未终止,并且原语可能在线程中止后保持锁定状态)。开发人员建议终止整个过程,因为操作系统将在进程停止时释放同步原语。
将AppDomain
卸载帮助,如果有人会使用Slim
同步原语吗? (使用.net 4.0添加了几个与线程相关的新类:ManualResetEventSlim
,SemaphoreSlim
,ReaderWriterLockSlim
)。
文档说这些原语不能在不同的进程之间使用,因为原语的实现代码是完全管理的。但我不明白 - 这些原语是否会通过AppDomain
边界。 (见Can't set synchronization context when using appdomains)
UPD: 我信任的所有代码,包括我卸载的域内的代码。当终止它时,我不想让线程工作。我想终止(中止)线程而不是“设置标志”和“制作漂亮的架构”。如果首先创建额外的线程是必要的(我认为这是在单独的域中开始后台处理以创建一个更多的线程时所必需的),我会这样做。我不想使用“设置标志”方法,因为它要求我使用标志检查来设置后台算法,我不应该,它是运行时或编译器应该为我自动化该仪器。现在没有这样的工具,这就是为什么我试图通过域卸载来应用这种方法。
在每条指令之间(或在深嵌套循环中)添加检查将显着减慢代码。在随机位置添加检查不会保证提示终止。如果可以解决编写中止安全代码的困难,为什么不尝试中止线程并卸载域?
答案 0 :(得分:2)
您误解了AppDomain
,Process
和Thread
定义 - AppDomains always lives in one process, but one process can be a master for different AppDomains
*:
在单个进程中运行多个应用程序的能力 大大提高了服务器的可扩展性。
Thread
类似,仅供提及。因此,您的问题的答案是是,slim synchronization primitives将适用于各种AppDomains
,因为此类架构中没有跨进程调用,只有各种过程的逻辑区别。
对于链接的问题,那里的同步原语没有问题,只有SynchronizationContext
, Thread
- 具体,而不是AppDomain
特异性。
您可以在此处找到关于AppDomain
,Thread
和Process
之间差异的绝佳答案:Difference between AppDomain, Assembly, Process, and a Thread
至于卸载AppDomain,我认为您可以重构代码,因为您可以将Thread
工作者AppDomain
启动到您对系统资源有限的using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var ad = AppDomain.CreateDomain("WhereTheWorkHappens");
Task<string> t = DoWorkInOtherDomain(ad);
Console.WriteLine("waiting...");
Console.WriteLine(t.Result);
Console.ReadLine();
}
static Task<string> DoWorkInOtherDomain(AppDomain ad)
{
var ch = new MarshaledResultSetter<string>();
Worker worker = (Worker)ad.CreateInstanceAndUnwrap(typeof(Worker).Assembly.FullName, typeof(Worker).FullName);
worker.DoWork(ch);
return ch.Task;
}
class Worker : MarshalByRefObject
{
public void DoWork(MarshaledResultSetter<string> callback)
{
ThreadPool.QueueUserWorkItem(delegate
{
Thread.SpinWait(500000000);
callback.SetResult(AppDomain.CurrentDomain.FriendlyName);
});
}
}
class MarshaledResultSetter<T> : MarshalByRefObject
{
private TaskCompletionSource<T> m_tcs = new TaskCompletionSource<T>();
public void SetResult(T result) { m_tcs.SetResult(result); }
public Task<T> Task { get { return m_tcs.Task; } }
}
}
,并等待它完成,像it mentioned here:
<UserControl x:Class="WpfApplication7.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Border Background="Blue"/>
</UserControl>
作为一个额外的想法,你可以阅读Sandboxing your code with TPL
,我认为这是更好的方法,因为你不手动管理系统资源,并且你的非被黑客入侵的可能性较小可信代码。
此外,您还可以找到包含Cross-AppDomain Marshaling friendly TPL wrappers for APM
的GitHub项目