我有两个项目的解决方案。 在库项目中,我添加了一个公共静态bool变量,并将其设置为true。 然后在Windows窗体项目中我正在使用标志。 在Windows窗体项目设计器中,我添加了一个计时器,将其间隔设置为1000。
我正在构造函数中启动计时器。 然后在计时器打勾甚至我正在做:
private void timer1_Tick(object sender, EventArgs e)
{
if (SDKHandler.Saved == true)
{
timer1.Stop();
DisplayLastTakenPhoto();
TakePhotoButton.Enabled = true;
SDKHandler.Saved = false;
timer1.Start();
}
}
DisplayLastTakenPhoto()方法
private void DisplayLastTakenPhoto()
{
string mypath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "RemotePhoto");
var directory = new DirectoryInfo(mypath);
var myFile = directory.EnumerateFiles()
.Where(f => f.Extension.Equals(".jpg", StringComparison.CurrentCultureIgnoreCase) || f.Extension.Equals("raw", StringComparison.CurrentCultureIgnoreCase))
.OrderByDescending(f => f.LastWriteTime)
.First();
if (WaitForFile(myFile.FullName) == true) LiveViewPicBox.Load(myFile.FullName);
}
和WaitForFile方法
bool WaitForFile(string fullPath)
{
int numTries = 0;
while (true)
{
++numTries;
try
{
using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None, 100))
{
fs.ReadByte();
break;
}
}
catch (Exception ex)
{
if (numTries > 10)
{
return false;
}
System.Threading.Thread.Sleep(500);
}
}
return true;
}
有时不是所有的时间,但在某些情况下,当它调用方法DisplayLastTakenPhoto()时;连续两次。即使我先停止计时器,我也在做timer1.Stop();但在某些情况下我仍然看到两次调用的方法。
并且第二次使程序挂起/冻结有时甚至持续1-3秒。
答案 0 :(得分:2)
查看MSDN documentation中的备注和备注。这很可能导致您观察到的行为:
通过调用Stop禁用定时器后调用Start将导致Timer重新启动中断的间隔。如果您的Timer设置为5000毫秒间隔,并且您在大约3000毫秒内调用Stop,则调用Start将导致Timer在提升Tick事件之前等待5000毫秒。
在Windows窗体应用程序中的任何计时器上调用Stop可以立即处理来自应用程序中其他Timer组件的消息,因为所有Timer组件都在主应用程序线程上运行。如果你有两个Timer组件,一个设置为700毫秒,一个设置为500毫秒,你在第一个Timer上调用Stop,你的应用程序可能会先收到第二个组件的事件回调。
当您的应用程序临时冻结以检查究竟发生了什么时,您也可以在调试器中点击暂停。
答案 1 :(得分:2)
你看到的是完全正常的。那一秒快速 ,尤其是在调试时。然后您的代码将尝试再次加载相同的图像文件。除了第二次你的WaitForFile()失败并挂起你的UI五秒钟。因为文件被锁定,PictureBox.Load()会锁定图像文件。由Image类使用的内存映射文件生成,这是一种非常有效的方法,可以将图像的像素数据保留在页面文件之外。但是因为产生难以诊断的图像文件操作失败而臭名昭着:)
您需要改进代码,不要尝试两次加载相同的文件。简单地通过使用存储最后使用的路径的变量来完成。并且保持超时更加温和,5秒是相当长的时间来挂起UI,最多一秒是合理的。另请注意,您根本不需要超时。由于计时器确保您在一秒钟后再次尝试。
文件锁定很容易避免btw,Bitmap(Image)构造函数可以完成该工作,它可以进行深层复制并允许您处理源Image。但在这种情况下,解决问题的方法并不正确。
您可以使用FileSystemWatcher而不是使用计时器进行轮询来进一步改进它。但是,您会再次遇到完全相同的锁定问题,在FSW事件触发的确切时刻很少可以访问该文件,因为正在编写文件的任何进程仍然没有关闭它。只要您知道这可能发生,那么这一切都可以解决。