Winforms 为什么是C++/CLI代码未将文件添加到列表框 我有一个C++代码,它可以检测文件在目录中被修改的时候,并将文件名添加到列表框中。

Winforms 为什么是C++/CLI代码未将文件添加到列表框 我有一个C++代码,它可以检测文件在目录中被修改的时候,并将文件名添加到列表框中。,winforms,file,listbox,c++-cli,Winforms,File,Listbox,C++ Cli,这是文件监视程序部分,位于启动监视过程的按钮内 private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { array<String^>^ args = Environment::GetCommandLineArgs(); FileSystemWatcher^ fsWatcher = gcnew FileSystemWatcher( ); fsWatc

这是文件监视程序部分,位于启动监视过程的按钮内

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
    array<String^>^ args = Environment::GetCommandLineArgs();

    FileSystemWatcher^ fsWatcher = gcnew FileSystemWatcher( );
    fsWatcher->Path = "C:\\users\\patchvista2";
    fsWatcher->IncludeSubdirectories = true;
    fsWatcher->NotifyFilter = static_cast<NotifyFilters> 
              (NotifyFilters::FileName | 
               NotifyFilters::Attributes | 
               NotifyFilters::LastAccess | 
               NotifyFilters::LastWrite | 
               NotifyFilters::Security | 
               NotifyFilters::Size );

    Form1^ handler = gcnew Form1(); 
    fsWatcher->Changed += gcnew FileSystemEventHandler(handler, &Form1::OnChanged);
    fsWatcher->Created += gcnew FileSystemEventHandler(handler, &Form1::OnChanged);

    fsWatcher->EnableRaisingEvents = true;
}
private:System::Void按钮1\u单击(系统::对象^sender,系统::事件参数^e){
数组^args=Environment::GetCommandLineArgs();
FileSystemWatcher^fsWatcher=gcnewfilesystemwatcher();
fsWatcher->Path=“C:\\users\\patchvista2”;
fsWatcher->IncludeSubdirectories=true;
fsWatcher->NotifyFilter=static\u cast
(NotifyFilters::FileName |
NotifyFilters::Attributes|
NotifyFilters::LastAccess|
NotifyFilters::LastWrite|
NotifyFilters::Security |
(大小);
Form1^handler=gcnewform1();
fsWatcher->Changed+=gcnewfilesystemeventhandler(处理程序,&Form1::OnChanged);
fsWatcher->Created+=gcnewfilesystemeventhandler(处理程序,&Form1::OnChanged);
fsWatcher->EnableRaisingEvents=true;
}
对于onchange部分,我有以下代码

void OnChanged (Object^ source, FileSystemEventArgs^ e)
{
    // Here is the problem
    MessageBox::Show(e->FullPath);
    listBox1->Items->Add(e->FullPath);
    // End problem

    System::Security::Cryptography::MD5 ^ md5offile = MD5CryptoServiceProvider::Create();
    array<Byte>^ hashValue;
    FileStream^ fs = File::Open(e->FullPath, IO::FileMode::Open, IO::FileAccess::Read, IO::FileShare::ReadWrite);
    fs->Position = 0;
    hashValue = md5offile->ComputeHash(fs);
    PrintByteArray(hashValue);
    fs->Close();
    Application::DoEvents();
}
void OnChanged(对象^source,文件系统目标^e)
{
//问题就在这里
MessageBox::Show(e->FullPath);
列表框1->项目->添加(e->完整路径);
//终点问题
System::Security::Cryptography::MD5^md5offile=MD5CryptoServiceProvider::Create();
数组^hashValue;
FileStream ^fs=File::Open(e->FullPath,IO::FileMode::Open,IO::FileAccess::Read,IO::FileShare::ReadWrite);
fs->Position=0;
hashValue=md5ofile->ComputeHash(fs);
PrintByteArray(哈希值);
fs->Close();
Application::DoEvents();
}
它将在消息框中显示文件名,但不会将其添加到列表框中。我试着让它将文件名显示到标签上,但也不起作用。一旦启动此代码循环,屏幕似乎就不会刷新。我在vb.net中有这段代码,它会将文件名添加到列表框中。有人能告诉我为什么没有将文件名添加到列表框中。

两件事:

  • 您需要让FileSystemWatcher保持活动状态。它很容易被垃圾收集在你现在拥有的地方。(创建一个类字段并将其粘贴在那里。)
  • 每当您对UI组件执行任何操作时,都需要将其添加到UI线程上 这里是#2的近似语法(我目前没有编译器,这可能不准确)

    void Form1::AddToListBox(字符串^filename)
    {
    listBox1->Items->Add(文件名);
    }
    void Form1::OnChanged(对象^source,文件系统目标^e)
    {
    Action^addDelegate=gcnew Action(此,&Form1::AddToListBox);
    此->调用(addDelegate,e->完整路径);
    ...
    }
    
    只是要清楚:这不是C++代码;一个正常运行的C++编译器必须拒绝它的基本语法错误(例如,<>代码>对象>源代码>代码>。在更新它之后,需要使列表框无效。我对管理C++不熟悉,所以我不知道你会怎么做。您还需要运行消息循环。@JerryCoffin这是C++/CLI我已经更正了问题标题。真的吗?为什么?C#不需要这个。。事件不是在UI线程上引发的吗?所有WinForms组件,无论是C#、VB还是C++/CLI,都只需要在UI线程上进行更改。我只是仔细检查了FileSystemWatcher的文档,我没有看到任何关于它在UI线程上引发事件的内容,所以我希望调用在C#中也是必需的。。我得回去看看我以前的FSW项目。。我不记得这样做过:/所以我添加了新的void Form1::AddToListBox(字符串^filename),这很好,但我添加了Action ^addDelegate=gcnew Action^(这个,&Form1::AddToListBox);此->调用(addDelegate,e->完整路径);在我的onchange代码的顶部,我得到了错误C3698:“System::Action^”:不能将此类型用作“gcnew”的参数,那么我该怎么办?编译器还使用[T=System::String^]表示“System::Action”(没有顶层“^”)吗?对于[T=System::String^],它告诉我要修复什么
    void Form1::AddToListBox(String^ filename)
    {
        listBox1->Items->Add(filename);
    }
    
    void Form1::OnChanged(Object^ source, FileSystemEventArgs^ e)
    {
        Action<String^>^ addDelegate = gcnew Action<String^>(this, &Form1::AddToListBox);
        this->Invoke(addDelegate, e->FullPath);
        ...
    }