FileSystemWatcher 不会在函数后触发

FileSystemWatcher doesn't fire after function

我正在创建一个 C# 程序来帮助我测试我开发的网站,但遇到了一些问题。目标是让程序存储我网站的不同帐户及其关联的 cookie,以便它可以自动登录以进行测试。现在我正在使用 Playwright 来实现浏览器自动化以及 cookie 存储(这些都没有问题)。但是,我的问题似乎是因为 FileSystemWatcher 在我保存 cookie 后没有触发。

我的目标是在每次添加新帐户时使用我保存的帐户更新我的程序界面。为此,我使用 FileSystemWatcher 调用一个函数,该函数从一个文件中重新加载我的所有用户帐户。

我创建 FileSystemWatcher 的函数如下所示:

private string filesPath = @"" + Path.GetDirectoryName(Application.ExecutablePath) + "\inc";

private void CreateFileWatcher()
{
    FileSystemWatcher fsWatcher = new FileSystemWatcher(filesPath, "accounts.dat");
    fsWatcher.NotifyFilter = NotifyFilters.LastWrite;

    fsWatcher.Changed += new FileSystemEventHandler((object s, FileSystemEventArgs e) =>
    {
        // Load accounts
    });

    fsWatcher.EnableRaisingEvents = true;
}

我想特别关注那个“accounts.dat”文件,所以我将它添加为过滤器,正如您从我的代码中看到的那样。

为了添加新帐户,我的函数如下所示:

private void CreateAccount() {
    Dictionary<Guid, Account> accounts;

    Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
    BinaryFormatter bf = new BinaryFormatter();

    try
    {
        accounts = (Dictionary<Guid, Account>)bf.Deserialize(stream);
        accounts.Add(account.UUID, account);
    }
    catch
    {
        accounts = new Dictionary<Guid, Account>();
        accounts.Add(account.UUID, account);
    }
    stream.Close();

    stream = new FileStream(fileName, FileMode.Truncate, FileAccess.Write);
    bf.Serialize(stream, accounts);
    stream.Close();

    // Then I call my login function that logs the account in and saves the cookies
}

我的登录函数是:

public static Task Login(Account account, string url) {
    try
    {
        using var playwright = await Playwright.CreateAsync();
        await using var browser = await playwright.Chromium.LaunchAsync(new()
        {
            Headless = false,
        });
        await using var context = await browser.NewContextAsync(new()
        {
            ViewportSize = new ViewportSize() { Height = 450, Width = 500 }
        });

        // Create page
        var page = await context.NewPageAsync();
        await page.GotoAsync(url);

        // Sign in
        await Login(page, account);

        // Save auth state
        string cookies = await context.StorageStateAsync();

        // Write cookies
        await WriteCookies(cookies, account);
    }
    catch (Exception e)
    {
        // Log to my logfile
    }
}

最后,我保存 cookie 的函数是:

public static async Task WriteCookies(string cookies, Account account) {
    // Create list of accounts
    Dictionary<Guid, string> sessions;

    Stream stream = new FileStream(sessionsFile, FileMode.Open, FileAccess.Read);
    BinaryFormatter bf = new BinaryFormatter();

    try
    {
        sessions = (Dictionary<Guid, string>)bf.Deserialize(stream);
        sessions.Add(account.UUID, cookies);
    }
    catch
    {
        sessions = new Dictionary<Guid, string>();
        sessions.Add(account.UUID, cookies);
    }
    stream.Close();

    stream = new FileStream(sessionsFile, FileMode.Truncate, FileAccess.Write);
    bf.Serialize(stream, sessions);
    stream.Close();
}

正如您从我的代码中看到的那样,每个会话都通过帐户 Guid 关联到一个用户帐户,因此我以后可以轻松访问与该帐户相关的正确会话。我认为这个问题源于我的写入 cookie 函数是异步的,所以它抛弃了 FileSystemWatcher,所以我尝试分离会话和帐户来解决这个问题,但没有成功。我似乎无法弄清楚我做错了什么,但似乎该事件在首次创建帐户时触发,然后一旦我编写了 cookie,它就再也不会触发,直到我手动重新加载表单。感谢您的帮助。

此外,现在我正在打开文件以获取现有数据,关闭它,然后以 Truncate 模式重新打开它,因为我想每次都清除文件所以如果你推荐一个更好的方法将新对象添加到我的列表中我很乐意听到它们。

谢谢!

尝试将 FileSystemWatcher 创建为程序级变量而不是方法中的局部变量,看看是否能解决问题。

即将 FileSystemWatcher 移动到私有局部变量。