微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 using 变量会在离开方法之前自行处理?

如何解决为什么 using 变量会在离开方法之前自行处理?

using PuppeteerSharp;
using System;
using System.Threading.Tasks;

namespace Video_Handler
{
    public class VideoHost
    {
        private static bool Is_HTTPS_URL(string url)
        {
            Uri uriResult;

            bool result = Uri.TryCreate(url,UriKind.Absolute,out uriResult) && (uriResult.Scheme == Uri.UriSchemeHttps);
            return result;
        }

        #region browserCreationCode
        private static async Task FectchbrowserIfItIsNotthere()
        {
            var browserFetcher = new browserFetcher();
            await browserFetcher.DownloadAsync();
        }
        internal static async Task<Page> GetPageAsync(string url,bool isPageInvisible = true,Action<Page> action)
        {
            if(!Is_HTTPS_URL(url))
            {
                throw new ArgumentException($"The url | {url} | is not an https url.");
            }
            await FectchbrowserIfItIsNotthere();
            await using var browser = await Puppeteer.LaunchAsync(
                new LaunchOptions { Headless = isPageInvisible });
            await using var page = await browser.NewPageAsync();
            await page.GoToAsync(url);
            action(page);
            return page;
        }
    }
}
//Boiler Plate code
async static void Main()
{
  Action<Page> action = (page) => Foo(page);
  await GetPageAsync("https://google.com",false,action);
}
public static async Task Foo(Page p){ 
   await p.EvaluateExpression("//fill google search bar"); //first line
   await p.EvaluateExpression("//click search button");  //second line
   await p.WaitForNavigationAsync(); //third line
   await p.EvaluateExpression("alert("hi")"); //fourth line
}

我遇到了一个问题,当我将 page 变量发送到接受页面变量的操作时,它会导致页面或浏览器变量被处理。根据我对使用的理解,只有在我离开函数的括号时才会发生这种情况。我已经阅读了关于 using 的 Microsoft 文档,但我找不到任何内容告诉我页面变量在转到函数中的另一个函数时会自行处理使用变量在。

此外,有时代码将能够评估函数的某些表达式,但通常会在第三次失败。但是,如果我一步一步调试和运行,它总是在第一行失败。这就是让我相信这是一个处置问题的原因。

如果有人想知道为什么我没有从 browserpage 变量中删除 using 并自己处理它们,我有两个原因。一,我没有处理非托管代码的经验,当我尝试将处理添加到终结器/析构函数时,它不起作用,其次,我不想编写代码来完成语言已经为我做的事情.

解决方法

问题是使用 Action 而不是 Func

Action 总是返回空值。由于 Action 正在调用的函数是一个异步方法,但没有发送该方法的输出,因此会导致调用 Action 的函数退出,从而释放未管理的资源。 Func 保留输出以便可以等待它,因此主线程被阻塞直到完成以防止非托管资源被提前释放。

async static void Main()
{
   Func<FileStream,Task> func = (FileStream fs) => Foo(fs); //Input to function is FileStream and Output of Function is Task
   Action<FileStream> action = (FileStream fs) => Foo(fs); //Equivalent to Func<FileStream,void>
   using var fs = new FileStream();
   //action(fs); //This can fail if the main thread is finished before it
   await func(fs); //This will succeed since the main thread is blocked till completion

}
async static Task Foo(FileStream fs) => await fs.SomeLongAsyncMethod();


版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。