Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.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
C# 我需要using语句来锁定资源,我的自定义解决方案是否健壮?_C#_.net_Multithreading_Generics_Using Statement - Fatal编程技术网

C# 我需要using语句来锁定资源,我的自定义解决方案是否健壮?

C# 我需要using语句来锁定资源,我的自定义解决方案是否健壮?,c#,.net,multithreading,generics,using-statement,C#,.net,Multithreading,Generics,Using Statement,我所处的情况是,清理非托管资源是一个关键部分。为了解决这个问题,我改变了这个 void SomeMethod() { //work using (var doc = SpreadsheetDocument.Open(results.FileName, true)) { //use doc. } } 对此 public static readonly object Locker = new object(); void SomeMethod() {

我所处的情况是,清理非托管资源是一个关键部分。为了解决这个问题,我改变了这个

void SomeMethod()
{
    //work
    using (var doc = SpreadsheetDocument.Open(results.FileName, true))
    {
        //use doc.
    }
}
对此

public static readonly object Locker = new object();
void SomeMethod()
{
    //work
    {//scoping doc
        var doc = SpreadsheetDocument.Open(results.FileName, true);
        try
        {
             //use doc
             //At some point wrapping a critical section via lock(Locker) 
        }
        finally
        {
            lock (Locker)
            {
                if (doc != null) ((IDisposable)doc).Dispose();
            }
        }
    }
}
我认为,这是一个丑陋而脆弱的解决方案。因此,我将其更改为以下内容

public static readonly object Locker = new object();
void SomeMethod()
{
    //work
    CustomUsingWithLocker(SpreadsheetDocument.Open(results.FileName, true), Locker, doc =>
    {
        //use doc
        //At some point wrapping a critical section via lock(Locker) 
    });
}

public static void CustomUsingWithLocker<T>(T resource, object locker, Action<T> body)
    where T : class, IDisposable 
{
    try
    {
        body(resource);
    }
    finally
    {
        lock (locker)
        {
            if (resource != null) resource.Dispose();
        }
    }
}
公共静态只读对象锁定器=新对象();
void方法()
{
//工作
CustomUsingWithLocker(电子表格文档.Open(results.FileName,true)),Locker,doc=>
{
//使用文档
//在某个点上,通过锁(锁柜)包裹关键部分
});
}
公共静态void CustomUsingWithLocker(T资源、对象锁、操作体)
其中T:类,IDisposable
{
尝试
{
机构(资源);
}
最后
{
锁(储物柜)
{
if(resource!=null)resource.Dispose();
}
}
}

这个定制解决方案是否健壮?我能改进一下吗?是否保证释放任何非托管资源,如内置的Using语句?

这里的前提似乎是从多个线程多次调用
Dispose
。如果是这样的话,改变这个前提。即使
doc
被传递到另一个线程中使用它的某个地方,这个地方也不负责处理它,也不应该处理它。使用查找它在
结尾之外的处理位置,并将其更改为不这样做


如果
Dispose
没有在其他地方被调用,而您只是有一个非线程安全的
Dispose
方法,该方法不应从多个线程访问(即使您的代码目前足够聪明,不能这样做),并且您只是在尝试应用良好的防御编程,我想可以肯定地说,这里不需要这个。在这种特定的上下文中,这种方法的一个有效约束是,只有一个线程负责处理对象。

当文档不是共享对象时,为什么要用锁保护文档?在我的customUserWithLocker中,文档用于创建excel文档。如果在此期间处理不同的文档,将引发超时异常。通过锁定excel文档创建并锁定dispose调用,不会出现超时预期。我相信文件流是在文档之间共享的。从ASP.NET或其他服务器技术使用Office互操作是一个可怕的想法。这些API是为在桌面应用程序中使用而编写的,用于自动化Office(一套桌面应用程序)。服务器应用程序在许多方面都不同,因此在其中使用Office互操作是一个非常非常糟糕的主意。它也不受Microsoft支持,可能会违反您的Office许可证。请参见我相信
Dispose
仅被调用一次,在
finally
部分。如果一个文档位于关键部分(特别是在创建excel文档时),而另一个文档正在处理,则会引发异常。当我用某种公共互斥体包装临界部分和dispose时,我没有得到异常。因此,我相信您是对的,
Dispose
不是线程安全的。我认为文档正在共享文件流(很糟糕)。总体流程由一个
信号量lim(2)
包装,创建文档发生在disposing附近,因此它们经常发生冲突。