代码无法运行,因为另一个线程正在访问它。

3
我正在尝试在zip文件中编写xml。
static void Main(string[] args)
{
    String strPathofZip = @"C:/Work/Zip/PATHDATA DT2.zip";
    ZipFile zipFile = new ZipFile(strPathofZip);
    zipFile.BeginUpdate();
    foreach (ZipEntry ze in zipFile)
    {
        if (ze.Name == "SOURCEDATACONFIG.XML")
        {
            StreamReader s = new StreamReader(zipFile.GetInputStream(ze));
            {
                XmlDocument XDoc = new XmlDocument();
                XDoc.Load(s);
                XmlNodeList NodeList = XDoc.SelectNodes(@"R/I");
                foreach (XmlNode Node in NodeList)
                {
                    XmlElement Elem = (XmlElement)Node;

                    Elem.SetAttribute("url", "77");
                    //Elem.SetAttribute("url", "3");
                }
                XDoc.Save("SOURCEDATACONFIG.XML");
            }

            zipFile.Add(ze.Name);
        }
    }
    Console.WriteLine(zipFile.Name);
    zipFile.CommitUpdate();
    Console.ReadLine();
}

该代码在控制台应用程序中运行,并且Xml已更新,但是

如果我尝试将相同的代码作为窗体中的函数使用... 它会抛出错误

private void settingAttributeinZipppedXML(string ZipPath)
{
    ZipFile zipFile = new ZipFile(ZipPath);
    zipFile.BeginUpdate();
    foreach (ZipEntry ze in zipFile)
    {
        if (ze.Name == "SOURCEDATACONFIG.XML")
        {
            using (StreamReader s = new StreamReader(zipFile.GetInputStream(ze)))
            {
                XmlDocument XDoc = new XmlDocument();
                XDoc.Load(s);
                XmlNodeList NodeList = XDoc.SelectNodes(@"R/I");
                foreach (XmlNode Node in NodeList)
                {
                    XmlElement Elem = (XmlElement)Node;
                    Elem.SetAttribute("url", "12");
                }
                XDoc.Save("SOURCEDATACONFIG.XML");
            }
            zipFile.Add(ze.Name);
        }
    }
    zipFile.CommitUpdate();
}

错误为:

无法找到文件“C:\Work\Zip\PATHDATA DT2.zip.561.tmp”。

还有一件事:如果我调试代码一段时间程序就可以运行。

是什么原因导致了这种行为?

以下是堆栈跟踪:

堆栈跟踪:
       在 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 中
       在 System.IO.File.Move(String sourceFileName, String destFileName) 中
       在 ICSharpCode.SharpZipLib.Zip.DiskArchiveStorage.ConvertTemporaryToFinal() 中
       在 ICSharpCode.SharpZipLib.Zip.ZipFile.RunUpdates() 中
       在 ICSharpCode.SharpZipLib.Zip.ZipFile.CommitUpdate() 中
       在 SDEProfilePathEditor.SDEProfilePathEditorForm.settingAttributeinZipppedXML(String ZipPath) 中
       在 System.Windows.Forms.Control.OnClick(EventArgs e) 中
       在 System.Windows.Forms.Button.OnClick(EventArgs e) 中
       在 System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) 中
       在 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 中
       在 System.Windows.Forms.Control.WndProc(Message& m) 中
       在 System.Windows.Forms.ButtonBase.WndProc(Message& m) 中
       在 System.Windows.Forms.Button.WndProc(Message& m) 中
       在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 中
       在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 中
       在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 中
       在 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 中
       在 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 中
       在 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 中
       在 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 中
       在 System.Windows.Forms.Application.Run(Form mainForm) 中
       在 SDEProfilePathEditor.Program.Main() 中
       在 System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 中
       在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 中
       在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 中
       在 System.Threading.ThreadHelper.ThreadStart_Context(Object state) 中
       在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 中
       在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 中
       在 System.Threading.ThreadHelper.ThreadStart() 中
  内部异常:

你是不是也想在控制台应用程序示例中写 using (StreamReader s...,还是这只是一个打字错误?这有点重要... - Andrei V
你的两个应用程序明显不同。它找不到的路径与控制台应用程序中的路径不同。尝试弄清楚为什么在WinForms应用程序中指定了不同的路径。 - Khan
是的,表单中的参数就是这个路径...正如我告诉过你的那样,它有时会运行,但并不总是... - arc
当我调试一段时间并检查值时...它显示C:\Work\Zip\PATHDATA DT2.zip,然后运行,但是当我直接运行它时,由于某些线程,我认为它会为自己使用创建.zip.tmp...并尝试编辑它...从而造成混乱... - arc
不,它们并没有不同。只是在Windows Forms中用户会选择zip路径,而在控制台应用程序中我手动编写了它。这个Windows表单也需要一些时间来运行。 - arc
显示剩余9条评论
3个回答

0

试试这个,确保在可执行文件运行的位置使用 currentDirectory()。

private void settingAttributeinZipppedXML(string ZipPath)
{
ZipFile zipFile = new ZipFile(Path.GetDirectoryName(Application.ExecutablePath) + "\\PATHDATA DT2.zip");
    zipFile.BeginUpdate();
    foreach (ZipEntry ze in zipFile)
    {
        if (ze.Name == "SOURCEDATACONFIG.XML")
        {
            using (StreamReader s = new StreamReader(zipFile.GetInputStream(ze)))
            {
                XmlDocument XDoc = new XmlDocument();
                XDoc.Load(s);
                XmlNodeList NodeList = XDoc.SelectNodes(@"R/I");
                foreach (XmlNode Node in NodeList)
                {
                    XmlElement Elem = (XmlElement)Node;
                    Elem.SetAttribute("url", "12");
                }
                XDoc.Save("SOURCEDATACONFIG.XML");
            }
            zipFile.Add(ze.Name);
        }
    }
    zipFile.CommitUpdate();
}

抱歉,我检查了表格,对我来说一切都很顺利。正在工作中。 - Rocky111
请使用此链接中的ICsharp:http://www.icsharpcode.net/opensource/sharpziplib/Download.aspx工作集在此处:https://www.dropbox.com/s/d4qc0v9um703mbz/ZipUpdator.zip - Rocky111
我想是这样。那我会使用其他方法。 - arc
是的,它正在工作。但这就是问题所在,为什么有时会出现错误。如果您现在可以看到堆栈跟踪。 - arc

0

Console.WriteLine 只在控制台应用程序中工作。因此不会显示任何输出,似乎您的应用程序是 Windows 窗体应用程序。

如果您想在 Windows 窗体应用程序中使用 Console.WriteLine 显示输出,只需添加此属性并从主窗体构造函数调用它。然后它也会打开控制台。

 public InsertNames()
 {
   AllocConsole();
   InitializeComponent();
 }

  [System.Runtime.InteropServices.DllImport("kernel32.dll")]
  private static extern bool AllocConsole();

那不是问题。如果您看到我的Windows Form版本,它是不同的。那里没有使用Console.WriteLine函数。该函数只是在zip文件中的xml文件中进行属性编辑。那才是主要任务。 - arc

0
问题是其他线程已经打开了该zip文件。然后我的函数创建了一个临时的zip文件,这就造成了问题。

zipFile.Close();

被添加以关闭已打开的zip文件。

感谢大家的建议。


整个讨论似乎毫无意义,因为你改变了问题,出现了错误。 - Rocky111

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接