繁体   English   中英

如何在带有 FileSystemWatcher 的 MAUI 中使用 Clipboard.Default.SetTextAsync

[英]How to use Clipboard.Default.SetTextAsync in MAUI with FileSystemWatcher

我在我的项目中关注了 https://learn.microsoft.com/en-us/do.net/maui/platform-integration/data/clipboard?view.net-maui-7.0 ,我了解到:

必须在主用户界面线程上访问剪贴板。 有关如何在主用户界面线程上调用方法的更多信息,请参阅 MainThread。

我不能在没有错误的情况下执行Clipboard.Default.SetTextAsync(url) ,而且我不明白我哪里做错了。

  • URL是通过FileSystemWatcher的OnCreated()方法生成的。
  • 我知道这不是 UI 线程,但我触发了一个我认为应该启用 UI 线程操作的事件

我想修复下面的代码,以便我可以在 macOS 中毫无问题地使用我的应用程序。

也可以通过拉取以下两个项目查看GitHub中的代码:

我的代码如下。

using HelpersLib;
using Microsoft.Extensions.Logging;
using ShareX.HelpersLib;
using ShareX.UploadersLib;

namespace UploaderX;

public partial class MainPage : ContentPage
{
    int count = 0;
    private FileSystemWatcher _watcher;

    private string _watchDir;
    private string _destDir;

    public delegate void UrlReceivedEventHandler(string url);
    public event UrlReceivedEventHandler UrlReceived;

    public MainPage()
    {
        InitializeComponent();

        string AppDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "UploaderX");
        string AppSettingsDir = Path.Combine(AppDir, "Settings");
        App.Settings = ApplicationConfig.Load(Path.Combine(AppSettingsDir, "ApplicationConfig.json"));
        App.UploadersConfig = UploadersConfig.Load(Path.Combine(AppSettingsDir, "UploadersConfig.json"));
        App.UploadersConfig.SupportDPAPIEncryption = false;

        DebugHelper.Init(Path.Combine(AppDir, $"UploaderX-{DateTime.Now.ToString("yyyyMMdd")}-Log.txt"));

        _watchDir = Directory.Exists(App.Settings.CustomScreenshotsPath2) ? App.Settings.CustomScreenshotsPath2 : Path.Combine(AppDir, "Watch Folder");
        Helpers.CreateDirectoryFromDirectoryPath(_watchDir);

        _destDir = _watchDir;

        DebugHelper.Logger.WriteLine("Watch Dir: " + _watchDir);
        DebugHelper.Logger.WriteLine("Destination Dir: " + _destDir);

        _watcher = new FileSystemWatcher();
        _watcher.Path = _watchDir;

        _watcher.NotifyFilter = NotifyFilters.FileName;
        _watcher.Created += OnCreated;
        _watcher.EnableRaisingEvents = true;

        this.UrlReceived += MainPage_UrlReceived;

    }

    private async void MainPage_UrlReceived(string url)
    {
        await Clipboard.Default.SetTextAsync(url);
    }

    private void OnUrlReceived(string url)
    {
        UrlReceived?.Invoke(url);
    }

    private async void OnCounterClicked(object sender, EventArgs e)
    {
        count++;

        if (count == 1)
            CounterBtn.Text = $"Clicked {count} time";
        else
            CounterBtn.Text = $"Clicked {count} times";

        await Clipboard.Default.SetTextAsync(CounterBtn.Text);
    }

    async void OnCreated(object sender, FileSystemEventArgs e)
    {
        try
        {
            string fileName = new NameParser(NameParserType.FileName).Parse("%y%mo%d_%ra{10}") + Path.GetExtension(e.FullPath);
            string destPath = Path.Combine(Path.Combine(Path.Combine(_destDir, DateTime.Now.ToString("yyyy")), DateTime.Now.ToString("yyyy-MM")), fileName);
            FileHelpers.CreateDirectoryFromFilePath(destPath);
            if (!Path.GetFileName(e.FullPath).StartsWith("."))
            {
                int successCount = 0;
                long previousSize = -1;

                await Helpers.WaitWhileAsync(() =>
                {
                    if (!FileHelpers.IsFileLocked(e.FullPath))
                    {
                        long currentSize = FileHelpers.GetFileSize(e.FullPath);

                        if (currentSize > 0 && currentSize == previousSize)
                        {
                            successCount++;
                        }

                        previousSize = currentSize;
                        return successCount < 4;
                    }

                    previousSize = -1;
                    return true;
                }, 250, 5000, () =>
                {
                    File.Move(e.FullPath, destPath, overwrite: true);
                }, 1000);

                WorkerTask task = new WorkerTask(destPath);
                UploadResult result = task.UploadFile();
                DebugHelper.Logger.WriteLine(result.URL);
                OnUrlReceived(result.URL);
            }
        }
        catch (Exception ex)
        {
            DebugHelper.Logger.WriteLine(ex.Message);
        }

    }
}

生成一次URL报错:

在此处输入图像描述

您可以像这样使用MainThread.BeginInvokeOnMainThread()包装对SetTextAsync()的调用,以确保它被正确调用:

private void MainPage_UrlReceived(string url)
{
    MainThread.BeginInvokeOnMainThread(() => 
    {
        Clipboard.Default.SetTextAsync(url);
    });
}

也不需要awaitSetTextAsync()的调用,因为您是在事件处理程序中将其作为单一操作调用,这是不可等待的。

我知道这不是 UI 线程,但我触发了一个我认为应该启用 UI 线程操作的事件

通常,不能保证在主线程上调用 UI 类的事件处理程序。

您可以在官方文档中找到有关何时以及如何在主线程上调用方法的更多信息: https:https://learn.microsoft.com/en-us/do.net/maui/platform-integration/appmodel/main-thread ?view.net-maui-7.0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM