众所周知,ASP.NET展示了所谓的"线程敏捷性".简而言之,这意味着可以使用多个线程来完成单个请求,尽管一次不超过一个线程.这是一种优化,这意味着等待异步I/O的线程可能会返回到池并用于为其他请求提供服务.
但是,ASP.NET在移动请求时不会迁移所有与线程相关的数据.微软要么忘记这样做,要么认为使用线程局部存储(通过ThreadStatic属性变得容易)只是编码ASP.NET自己应该做的事情.
基于快速谷歌搜索,在我看来,避免这个问题的唯一方法是依赖HttpContext.如果ASP.NET决定在请求中切换线程,则确实会迁移上下文,因此克服了这个问题.但它反而引发了一个全新的问题:它将您的应用程序逻辑与HttpContext联系起来,从而与Web上下文联系起来.这在所有情况下都是不可接受的(事实上,我认为这在大多数情况下是不可接受的).此外,由于HttpContext是密封的并且具有内部构造函数,因此您无法模拟或存根,因此您的逻辑也变得不可测试.
根据这篇(旧)博客文章,CallContext不起作用,考虑到调用上下文在概念上恰好是一个逻辑线程,这是非常令人愤怒的!
有一种简单的方法可靠地实现"per-LOGICAL-thread"隔离,它可以在asp.net上下文以及其他上下文中使用吗?
如果没有,有没有人知道一个解决问题的轻量级第三方框架?是否StructureMap行为正确时ASP.NET迁移的主题?
我想要一个通用的答案,但是如果有人想知道,我正在看的具体用例是在SharePoint上下文中使用Entity Framework.遗憾的是,我们暂时坚持使用SP-2010和EF 3.5.EF基本上要求使用与最初读取的相同的上下文保存数据 - 否则您必须自己跟踪更改.我想介绍一个"当前模型"的概念.在处理每个HTTP请求时第一次调用模型时,应该对其进行实例化,然后在请求的持续时间内使用相同的模型实例.但是,如果在计时器作业的上下文中执行,依赖于"Model.Current"的代码也应该有效.我很好用计时器作业代码在完成它时显式处理模型(我想在SharePoint Web上下文中为HttpApplication.EndRequest的处理程序提供一个任务).
可能有理由不这样做,这也很有趣,但无论如何我真的很想知道在asp.net上下文中实现"逻辑线程隔离"的方法,因为它非常有用.
我正在使用VS-2010 Ultimate版本10.0.30319.1 RTMRel(来自关于框).
我编写了一个包含大量优秀XMLDOC(imho)的类库.由于我在各种解决方案中使用此库时不想进入的原因,项目本身不包括在内(如在右键单击解决方案中,添加现有项目..); 相反,我们只是添加对DLL的引用,就像它是第三方库一样.
在包含库的解决方案中,intellisense正常工作,我获得了XMLDOC的全部好处.不幸的是,那不是我将要使用它的地方!
在其他解决方案中,库只是一个引用的DLL,我得到intellisense,但没有XMLDOC.虽然我的图书馆基本上可以理解,但没有支撑轮,我想知道为什么会这样,以及我能做些什么呢.
非常可跳过的段落:我希望我脑子里那种相当愤世嫉俗的怀疑是我认为的那样毫无根据 - 也就是说,M $可能以某种方式"锁定"了这个功能,以便将它的访问权卖给第三方库开发人员...我想可以做一些事情,比如要求DLL由特定密钥签名,并提供一些在线付费服务,人们可以用这个密钥签署他们的DLL以启用功能,但考虑到它有多么宝贵拥有繁荣的第三方图书馆和组件开发人员的平台似乎不太可能有人打扰.
那么,有没有人有任何提示可以分享如何使这个工作?无论如何,每当我使用这个东西时,我都希望XMLDOC出现在intellisense中.:)
出于好奇,为什么编译器对待一个不受约束的泛型类型与它的typeof(object)有什么不同?
class Bar { }
class Foo
{
void foo(object thing)
{
((Bar)thing).ToString();
}
}
class Foo<T>
{
void foo(T thing)
{
((Bar)thing).ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
在上面,将"T thing"转换为Bar会导致编译器错误.然而,将"对象事物"转换为Bar是编译器允许我做的事情,当然我自担风险.
我没看到的是为什么.在.net对象中,毕竟是catch-all,运行时类型可以是盒装值或任何类型的对象.所以我没有看到编译器区分这两种情况的逻辑原因.我能做的最好就是"程序员希望编译器使用泛型类型进行类型检查,但不能使用对象".:)这就是它的全部吗?
顺便说一句,我知道我仍然可以通过简单的写作在Foo案例中完成我的演员阵容
((Bar)(object)thing).ToString();
Run Code Online (Sandbox Code Playgroud)
我只是想了解为什么编译器会这样做......
我想我知道我的意思,但我不太确定......
Framework 文档总结了该类型如下:
当方法调用对于对象的当前状态无效时抛出的异常。
有明确的情况,我想到的情况是当操作需要打开数据库但对象尚未使用连接到数据库所需的信息进行初始化时。
(切线:另一方面,ADO.NETs 还要求您显式打开连接的行为并不那么明确;DataAdapter 通过简单地打开连接 instad 与此不同,当且仅当它关闭时再次关闭它条目,我发现这很方便,并让自己成为一个 ADO.NET 包装器,该包装器对所有内容都使用此模式。当然,这意味着我冒着执行 2 ExecuteNonQuery 并不必要地将连接返回到两者之间的池的风险,但我仍然可以打开和关闭与获得异常相比,我想要的连接和这种性能损失算不了什么。)
我想我的问题的答案是,只有在这种明确的情况下,我们才应该抛出异常。但是在以下场景中哪种异常类型最合适:
public class FormatterMapping
{
Dictionary formattersByName = new ...();
public IFormatter GetFormatter(string key)
{
IFormatter f;
if (formattersByName.TryGetValue(key, out f))
return f;
else
throw new ??Exception("explanation of why this failed.");
}
}
我的第一反应是抛出 ArgumentException。然后我开始认为映射缺少一个键也可能与参数“错误”一样。基本上“获取格式化程序 X”操作是无效的,因为X 不在映射中,但我真的不知道 X 是否“应该在那里”或者在这里要求 X 是不明智的。
我当然可以通过返回 null 来规避整个问题,但这会打开一个更大、更深的蠕虫罐头。没有办法知道什么时候会使用返回值,所以稍后因 NullReferenceException 而爆炸的代码可能与出错的地方没有明显的关系。要么映射设置不当,要么使用它的代码要求一些不应该的东西。
避免该问题的另一种方法是使用 TryGetFormatter 选项,但我打算使用它的方式实际上调用者应该知道映射中的内容和不包含的内容,因此在用户代码上强制使用此模式不是也不错。
请不要回答我应该抛出 ApplicationException!无论您认为代码应该做什么,请提供原因。毕竟,这里真正有问题的是推理。
除非有人说服我,否则我倾向于 ArgumentException。从映射的角度来看,这个论点是错误的,所以至少有一个明确的推理支持这一点。:)
人们会认为guid中的字节分布是随机的,或者至少是非常平坦的.Guid.NewGuid总是制造包含4的 guid的原因是什么?其字符串表示包含4?
那是
Guid.NewGuid().的ToString( "N").包含( "4")
总是如此.
快速测试表明大多数字节出现在大约85%的Guids中,但是4个出现在100%中.也许这没关系,但我很想知道为什么.
[编辑]
我不是很清楚,所以编辑以提高我的问题的清晰度.
运行这个.不完全是深刻的,但有趣.
using System;
using System.Diagnostics;
namespace ConsoleApplication1 { class Program { static bool paused, exit;
static void Main(string[] args)
{
Console.WindowHeight = (int)(0.8*Console.LargestWindowHeight);
var reportInterval = TimeSpan.FromSeconds(0.15);
WriteLine(ConsoleColor.White, "X key to exit.");
Guid guid;
byte[] bytes;
long guidCount = 0;
var counts = new long[256];
var watch = Stopwatch.StartNew();
var cursorPos = new CursorLocation();
while (!exit)
{
if (!paused)
{
guid = Guid.NewGuid();
bytes = guid.ToByteArray();
++guidCount; …Run Code Online (Sandbox Code Playgroud) 我在概念上有一个像这样的WCF操作:
[OperationBehavior(TransactionScopeRequired = true)]
public void Foo()
{
try { DAL.Foo(); return Receipt.CreateSuccessReceipt(); }
catch (Exception ex) { return Receipt.CreateErrorReceipt(ex); }
}
Run Code Online (Sandbox Code Playgroud)
如果在执行DAL代码时出现问题(例如,外键约束违反),控制会按照我的预期传递到catch块.但是当方法返回时,似乎事务范围已经嗅出事务失败,并且它决定最好抛出异常以确保通知调用者它.
反过来我的客户端应用程序没有得到我想要返回的收据,而是一个例外:
System.ServiceModel.FaultException:
The transaction under which this method call was executing was asynchronously aborted.
Run Code Online (Sandbox Code Playgroud)
我的设计出了什么问题?
我可以让服务没有捕获任何东西,但这有它自己的问题,因为服务需要使用异常屏蔽,而客户端(系统内部的批处理工具)需要记录错误信息.该服务也会记录错误,但不会以与批处理相同的方式和相同的位置记录错误.
如果我们有一个带有子 SELECT 的 UPDATE,子查询是否可以在 READ COMMITTED 隔离下并发执行?
换句话说,以下是否存在竞争条件:
update list set [state] = 'active'
where
id = (select top 1 id from list where [state] = 'ready' order by id)
Run Code Online (Sandbox Code Playgroud)
换句话说,如果许多连接同时执行此 SQL,我们能否保证每次调用实际上更新一行(只要处于“就绪”状态的行存在)?
我做了一个符合W3规范的简单实现.在这里,我只是持有不同的合法字符集(合法的起始字符不同于以下字符)并使用string.Contains.但是这些合法字符组合令人惊讶地(对我来说)很大,只是在候选字符串的时候检查一个字符变得有点贵.
目前这不是一个问题,因为我需要每次执行一次(几秒钟,几分钟甚至几小时)验证一些字符串一次(花费几毫秒),但我很想知道其他人会建议什么.
这是我直截了当的实现:
using System;
using System.Text;
using Project.Common; // Guard
namespace Project.Common.XmlUtilities
{
static public class XmlUtil
{
static public bool IsLegalElementName(string localName)
{
Guard.ArgumentNotNull(localName, "localName");
if (localName == "")
return false;
if (NameStartChars.IndexOf(localName[0]) == -1)
return false;
for (int i = 1; i < localName.Length; i++)
if (NameChars.IndexOf(localName[i]) == -1)
return false;
return true;
}
// See W3 spec at http://www.w3.org/TR/REC-xml/#NT-NameStartChar.
static public readonly string NameStartChars = AZ.ToLower() + AZ + ":_" + GetStringFromCharRanges(0xC0, 0xD6, 0xD8, 0xF6, 0xF8, …Run Code Online (Sandbox Code Playgroud) .net ×4
c# ×2
algorithm ×1
asp.net ×1
concurrency ×1
exception ×1
generics ×1
guid ×1
intellisense ×1
perf ×1
sql-server ×1
throw ×1
transactions ×1
wcf ×1
xml ×1