Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
锁(obj)可能不工作c#_C#_Multithreading_Locking - Fatal编程技术网

锁(obj)可能不工作c#

锁(obj)可能不工作c#,c#,multithreading,locking,C#,Multithreading,Locking,我遇到了一个问题,我不确定是我还是线程锁定有问题 我有一个用于基本实用程序的类。该类中有一个创建或附加文本文件的方法。因为我使用它进行调试,所以我使用lock()方法来保持访问的单一性。除此之外,它似乎失败了,并允许多个线程进入被阻止的代码 运行测试线程时,它不会每次都抛出错误。这有点奇怪。正在创建50个线程/任务。每个线程都在使用下面的类向单个文件写入一行。它循环执行大约3100个单独的任务。但每个批次最多创建50个任务。当每个线程完成其任务时,将创建一个新线程来代替它。最后一批处理了3188

我遇到了一个问题,我不确定是我还是线程锁定有问题

我有一个用于基本实用程序的类。该类中有一个创建或附加文本文件的方法。因为我使用它进行调试,所以我使用lock()方法来保持访问的单一性。除此之外,它似乎失败了,并允许多个线程进入被阻止的代码

运行测试线程时,它不会每次都抛出错误。这有点奇怪。正在创建50个线程/任务。每个线程都在使用下面的类向单个文件写入一行。它循环执行大约3100个单独的任务。但每个批次最多创建50个任务。当每个线程完成其任务时,将创建一个新线程来代替它。最后一批处理了3188条命令并抛出了16个错误

我尝试过使用Monitor.Enter和Exit,但得到了相同的结果。我还尝试将StdLibLockObj设置为只读。结果都一样

错误:进程无法访问文件“ThreadExe.txt”,因为另一个进程正在使用该文件

static class StdLib { private static object StdLibLockObj = new object(); public static void WriteLogFile(string @AFileName, string FileData, bool AppendIfExists = true, bool AddAppPath = true) { lock (StdLibLockObj) { StreamWriter sw = null; try { if (AddAppPath) { AFileName = @Path.Combine(@ApplicationPath(), @AFileName); } if ((AppendIfExists) && File.Exists(AFileName)) { sw = File.AppendText(AFileName); } else { sw = File.CreateText(AFileName); } sw.Write(FileData); } finally { if (sw != null) { sw.Flush(); sw.Close(); sw.Dispose(); } sw = null; } } } } 静态类StdLib { 私有静态对象StdLibLockObj=新对象(); 公共静态void WriteLogFile(string@AFileName,string FileData,bool AppendIfExists=true,bool AddAppPath=true) { 锁(StdLibLockObj) { StreamWriter sw=null; 尝试 { if(AddAppPath) { AFileName=@Path.Combine(@ApplicationPath(),@AFileName); } if((AppendIfExists)&&File.Exists(AFileName)) { sw=File.AppendText(AFileName); } 其他的 { sw=File.CreateText(AFileName); } 软件写入(文件数据); } 最后 { 如果(sw!=null) { sw.Flush(); sw.Close(); sw.Dispose(); } sw=null; } } } } 我的背景主要是Delphi,在Delphi中,线程更细粒度


任何帮助都将不胜感激。

将您的StreamWriter条目包装在“使用”块中。这将消除锁定。有点像这样:

    public static void ErrorMessage(string logMessage)
    {
        using (StreamWriter sw_errors = new StreamWriter(m_errors, true))  
        {

            sw_errors.Write("\r\nLog Entry : ");
            sw_errors.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
                DateTime.Now.ToLongDateString());
            sw_errors.WriteLine("  :");
            sw_errors.WriteLine("  :{0}", logMessage);
            sw_errors.WriteLine("-------------------------------");

        }
    }

您的问题不在于锁定。看看你的错误信息;它说“…它正在被另一个进程使用”。因此,您需要找到答案的问题是,当您的代码试图写入此文件时,谁正在使用此文件(即,谁打开了该文件的文件句柄)。。。(顺便说一句,您不需要显式地执行sw.Flush()和sw.Close(),因为sw.Dispose()会处理这一点。)is也会将
StreamWriter
对象包装在一个对象周围。使用这种方式,您将不必使用finalize部分,因为
using(){}
将自动处理该对象。在附加call flush()之后,也要立即(仅供参考:即使错误消息提到“另一个进程”,也可能是您的程序打开了此文件的另一个句柄。如果您的代码在WriteLogFile以外的方法/位置接触/访问日志文件,请检查它们是否也在使用同一锁定对象同步访问
StdLibLockObj
。)仅使用WriteLogFile()方法访问该文件。在这种情况下,仅从新任务/线程调用该文件。看起来lock()方法没有阻止其他线程,或者Close()、Dispose()方法没有及时执行。因此,下一个线程进入访问该文件,而上一个线程的命令尚未完全执行。嗯,我感到有点尴尬…@elgonzo是正确的。还有另一个进程。它是操作系统。我在运行该进程之前刚刚删除了该文件。显然,这需要Windows几秒钟的时间删除后释放句柄。我直到今天早上才进行关联,喝了几杯浓咖啡。我真的很感谢所有花时间帮助我的人。我很抱歉。
使用
是尝试最终处置的(更好)选择,但它与锁定完全无关(即,您不能使用
使用
来“摆脱锁定”…)这是这个问题的根本原因。@smoore4-也许您需要进一步说明,因为文件没有关闭(无论是显式关闭还是通过使用块关闭)即使在释放StdLibLockObj上的锁并在同一文件上创建另一个StreamWriter后,文件句柄仍保持打开状态。实际上,在纯单线程工作流中,此代码仍可能出现文件锁定问题。@matt\u gregg,文件正在关闭(查看问题代码示例中的
finally
部分…)足够公平@elgonzo。来自MSDN:using语句实际上是一种语法便利。在编译时,语言编译器为try/catch块实现中间语言(IL)。