如何在同一应用程序的两个实例之间实现线程

本文关键字:两个 实例 之间 线程 实现 应用程序 | 更新日期: 2023-09-27 18:14:03

我有一个用c#开发的WinForm应用程序,它在我的本地驱动器中查找文件,如果没有找到它,则创建它,否则在文件中添加一些文本,然后读取它。

如果我在同一台机器上从两个不同的文件夹运行我的应用程序的两个实例,我如何同步这个?

我希望当第一个实例正在处理文件时,另一个实例不要中断。请注意,由于两者都是同一个应用程序的实例,因此它们对同一个目标文件夹进行读写操作。

是否有任何线程技术需要实现?

如何在同一应用程序的两个实例之间实现线程

不需要同步原语。您应该能够打开该文件以进行独占访问。这将防止任何其他应用程序干扰它。例如:

try
{
    using (var fs = new FileStream("foo", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
    {
        try
        {
            // do stuff with file.
        }
        catch (IOException ex)
        {
            // handle exceptions that occurred while working with file
        }
    }
}
catch (IOException openEx)
{
    // unable to open file
}

指定FileShare.None将阻止任何其他应用程序访问文件,当你打开它。

我认为最简单的解决方案是使用带有try catch的StreamReader和StreamWriter。如果一个实例打开了文件,另一个实例将抛出异常

  try
  {
    using (StreamWriter sw = new StreamWriter("my.txt", true))
    {
      sw.WriteLine(dir.Name);
    }
  }
  catch
  {
      //maybe retry in 5 seconds
  }

您可能想要查看互斥锁。它们允许您进行跨进程锁定。当一个互斥锁在一个程序中打开时,另一个程序中的互斥锁将等待。

您可以使用一个命名的系统级互斥锁,但这样做的问题是,另一个进程可能正在使用该文件(例如,用户)。文件系统是您所需要的所有同步。你应该这样做:

static bool AddTextToFile( string someText , int maxAttempts )
{
    if ( string.IsNullOrWhiteSpace(someText) ) throw new ArgumentOutOfRangeException( "someText"    ) ;
    if ( maxAttempts < 0                     ) throw new ArgumentOutOfRangeException( "maxAttempts" ) ;
    bool success = false ;
    int  attempts = 0 ;
    while ( !success )
    {
        if ( maxAttempts > 0 && ++attempts > maxAttempts ) { break ; }
        try
        {
            using ( Stream       s = File.Open( @"c:'log'my-logfile.txt" , FileMode.Append , FileAccess.Write , FileShare.Read ) )
            using ( StreamWriter sw = new StreamWriter(s,Encoding.UTF8) )
            {
                sw.WriteLine("The time is {0}. The text is {1}" , DateTime.Now , someText );
                success = true ;
            }
        }
        catch (IOException)
        {
            // the file is locked or some other file system problem occurred
            // sleep for 1/4 second and retry
            success = false ;
            Thread.Sleep(250);
        }
    }
    return success ;
}