我需要从文件中读取一个数字,然后递增数字并更新同一个文件,仅用于调试目的。我编写了这段代码,令我惊讶的是它引发了一个异常(它只是用于调试,但我仍然想要了解它):
该进程无法访问该文件,因为它正被另一个进程使用。
代码:
string path = Server.MapPath("~/Log.txt");
int newTotal = 0;
using (var reader = new StreamReader(path))
{
var total = reader.ReadLine();
if (total != null)
{
newTotal = int.Parse(total) + 1;
}
}
using (var writer = new StreamWriter(path, false))
{
// I added AutoFlush because I read somewhere on SO
// this will write to disk immediately
writer.AutoFlush = true;
writer.Write(newTotal);
}
然后我想把问题缩小到阅读或写作,所以我这样做了:
string path = Server.MapPath("~/Log.txt");
int newTotal = 0;
try
{
using (var reader = new StreamReader(path))
{
var total = reader.ReadLine();
if (total != null)
{
newTotal = int.Parse(total) + 1;
}
}
}
catch (Exception)
{
throw new System.Web.HttpException("During reading...");
}
try
{
using (var writer = new StreamWriter(path, false))
{
writer.AutoFlush = true;
writer.Write(newTotal);
}
}
catch (Exception)
{
throw new System.Web.HttpException("During writing...");
}
我得到了这个,所以这告诉我它发生在两个期间但随机发生:
During reading...
During writing...
During reading...
During writing...
During reading...
During reading...
During writing...
During writing...
During writing...
During writing...
During writing...
During reading...
During reading...
During reading...
请注意,此代码位于此方法中的MVC应用的Controller
中:
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
// Code is here
}
我使用 Process Explorer ,没有其他人正在使用该文件。
问题:我在这里处理的事情为什么例外?
起初我认为处理reader
可能会有延迟,但在这种情况下,所有异常都应该是reader
,但事实并非如此。另外,下面也会给出相同的例外:
this.path = Server.MapPath("~/Log.txt");
var total = System.IO.File.ReadAllText(this.path);
int newTotal = 0;
if (total != null)
{
newTotal = int.Parse(total) + 1;
}
System.IO.File.WriteAllText(this.path, newTotal.ToString());
没有线程。只需HTTP GET(常规和通过AJAX)。
修改
在使用Visual Studio 2015进行负载测试期间会发生这种情况。
答案 0 :(得分:0)
我遇到了这个问题,我通过添加while循环解决了这个问题。
尝试这样做,看看它是否能解决您的问题。
using (var reader = new StreamReader(path))
{
while (reader.Peek() > -1)
{
var total = reader.ReadLine();
newTotal = int.Parse(total) + 1;
}
}
答案 1 :(得分:0)
问题不在于:
reader
之前写入的代码。我使用控制台应用程序测试了确切的代码,但问题无法复制。static
),那么它们显然不是线程安全的。他们将被分享。但是这段代码不在静态环境中。以下是警告:
使用浏览器时,从未复制此问题。我也做了这样简单的事情:
protected override void Initialize(RequestContext requestContext)
{
System.IO.File.AppendAllText(tPath, "Thread enter and ID is: " +
System.Threading.Thread.CurrentThread.ManagedThreadId + Environment.NewLine);
// Placed all code here
System.IO.File.AppendAllText(tPath, "Thread exit and ID is: " +
System.Threading.Thread.CurrentThread.ManagedThreadId + Environment.NewLine);
}
现在使用上面的代码,当通过浏览器发出请求时,正如预期的那样,文件的内容如下所示。请注意,每个条目都是同步:
Thread enter and ID is: 35
Thread exit and ID is: 35
Thread enter and ID is: 11
Thread exit and ID is: 11
Thread enter and ID is: 29
Thread exit and ID is: 29
Thread enter and ID is: 36
Thread exit and ID is: 36
Thread enter and ID is: 27
Thread exit and ID is: 27
Thread enter and ID is: 11
Thread exit and ID is: 11
Thread enter and ID is: 29
Thread exit and ID is: 29
Thread enter and ID is: 8
Thread exit and ID is: 8
Thread enter and ID is: 11
Thread exit and ID is: 11
Thread enter and ID is: 36
Thread exit and ID is: 36
...
但是在Visual Studio负载测试期间,内容是这样的,并且方法的输入是不同步:
Thread enter and ID is: 12
Thread exit and ID is: 12
Thread enter and ID is: 29
Thread enter and ID is: 49
Thread enter and ID is: 51
Thread exit and ID is: 29
Thread exit and ID is: 51
Thread enter and ID is: 48
Thread exit and ID is: 48
Thread enter and ID is: 57
Thread exit and ID is: 57
Thread enter and ID is: 17
Thread exit and ID is: 17
Thread enter and ID is: 55
Thread exit and ID is: 55
Thread enter and ID is: 42
Thread exit and ID is: 42
Thread enter and ID is: 47
Thread enter and ID is: 55
...
<强>结论强>
总之,在使用Visual Studio进行负载测试时,调用行为与浏览器的调用行为不完全相同。由于某种原因,每个线程都没有给出自己的类实例。我不知道为什么,但如果有人这样做,请插入。如果你问我,我认为这是一个公牛:如果它做了一些完全违反ASP.NET架构的事情,我怎么能进行负载测试呢? / em>的
<子> 1。 Thread safety ASP.NET 子>