System.io.directory :: getFiles()从AX 2009进行轮询,每10秒仅查看新文件



我在AX 2009中编写了代码,以每1秒钟在网络驱动器上进行轮询目录,等待来自另一个系统的响应文件。我注意到使用文件资源管理器窗口,我可以看到文件显示,但是我的代码在文件显示后几秒钟没有看到和处理文件 - 最多9秒(和9个民意调查)!

使用ClrInterop

调用AX代码System.IO.Directory::GetFiles()
interopPerm = new InteropPermission(InteropKind::ClrInterop);
interopPerm.assert();
files = System.IO.Directory::GetFiles(#POLLDIR,'*.csv');
// etc...
CodeAccessPermission::revertAssert();

经过大量的实验,它出现了我程序一生中的第一次,我称::GetFiles()的名字,它以10秒的时间开始了一个名义上的"滴答时钟"。每10秒钟只能拨打每10秒即可出现的任何新文件,尽管它们确实报告了自第一个拨打::GetFiles()以来的10s" tick"上发现的文件。

如果,当我启动程序时,该文件不存在,则所有其他呼叫 ::GetFiles(),第一个呼叫后1秒钟,后2秒钟,等等,最多9秒,只是看不到文件,即使自第一次通话后0.5秒起可能坐在那里!

然后,可靠地,重复地,第一个呼叫后的10次通话将找到该文件。那么,从11到19s的任何电话都不会看到任何可能出现的新文件,但是第一个呼叫后的20次呼叫将可靠地看到任何新文件。等等,每10秒。

进一步的调查显示,如果轮询目录在AX AOS计算机上,则不会发生,并且在文件出现在目录中后的呼叫时,该文件立即在呼叫上找到。

但是,无论我在哪种服务器上进行哪种网络驱动器,这10s的数字都是可靠且可重复的。

我们的网络当然没有10秒的延迟来查看文件;正如我所说,轮询目录上的文件资源管理器窗口立即看到该文件。

发生了什么?

听起来您的问题是由SMB缓存引起的 - 来自此技术页面:

名称,类型和ID
目录缓存[dword] Directorycachelifetime

注册表密钥缓存设置由 HKEY_LOCAL_MACHINESystemCurrentControlSetServicesLanmanworkstationParameters

这是最新目录枚举的缓存 客户。随后由客户应用程序提出的枚举请求为 以及目录中有关文件的元数据查询 从缓存。客户端还使用目录缓存来确定 目录中的文件存在或不存在 信息以防止客户反复试图打开 已知服务器上不存在的文件。这个缓存可能是 影响在多台计算机上运行的分布式应用程序 访问服务器上的一组文件 - 应用程序使用 避免频段机制,以互相发出信号 修改/添加/删除服务器上的文件。


简而言之尝试设置注册表密钥

HKEY_LOCAL_MACHINESystemCurrentControlSetServicesLanmanworkstationParametersDirectoryCacheLifetime

0

感谢@jan B. Kjeldsen,我能够使用filesystemwatcher解决我的问题。这是我在X 中的实现:

class SelTestThreadDirPolling
{
}
public server static Container SetStaticFileWatcher(str _dirPath,str _filenamePattern,int _timeoutMs)
{
    InteropPermission interopPerm;
    System.IO.FileSystemWatcher fw;
    System.IO.WatcherChangeTypes watcherChangeType;
    System.IO.WaitForChangedResult res;
    Container cont;
    str fileName;
    str oldFileName;
    str changeType;
    ;
    interopPerm = new InteropPermission(InteropKind::ClrInterop);
    interopPerm.assert();
    fw = new System.IO.FileSystemWatcher();
    fw.set_Path(_dirPath);
    fw.set_IncludeSubdirectories(false);
    fw.set_Filter(_filenamePattern);
    watcherChangeType = ClrInterop::parseClrEnum('System.IO.WatcherChangeTypes', 'Created');
    res = fw.WaitForChanged(watcherChangeType,_timeoutMs);
    if (res.get_TimedOut()) return conNull();
    fileName = res.get_Name();
    //ChangeTypeName can be: Created, Deleted, Renamed and Changed
    changeType = System.Enum::GetName(watcherChangeType.GetType(), res.get_ChangeType());
    fw.Dispose();
    CodeAccessPermission::revertAssert();
    if (changeType == 'Renamed') oldFileName = res.get_OldName();
    cont += fileName;
    cont += changeType;
    cont += oldFileName;
    return cont;
}
void waitFileSystemWatcher(str _dirPath,str _filenamePattern,int _timeoutMs)
{
    container cResult;
    str filename,changeType,oldFilename;
    ;
    cResult=SelTestThreadDirPolling::SetStaticFileWatcher(_dirPath,_filenamePattern,_timeoutMs);
    if (cResult)
    {
        [filename,changeType,oldFilename]=cResult;
        info(strfmt("filename=%1, changeType=%2, oldFilename=%3",filename,changeType,oldFilename));
    }
    else
    {
        info("TIMED OUT");
    }
}
void run()
{;
    this.waitFileSystemWatcher(@'\myservermydir','filepattern*.csv',10000);
}

我应该确认以下内容,以形成我的X 实现的基础:

https://blogs.msdn.microsoft.com/floditt/2008/09/01/how-to-mimplement-filesystemystemwatcher-with-with-x/

我猜达克萨利(Daxaholic)的答案是正确的,但是您可以尝试其他解决方案(例如

在您的情况下,我宁愿等待文件而不是对文件进行轮询。使用Filesystemwatcher,从文件创建到您的流程醒来将有很小的延迟。使用更棘手,但是避免进行投票是好东西。我从来没有通过网络使用它。

最新更新