为什么 using 变量在离开方法之前自行处理?
Why is the using variable disposing itself before leaving the method?
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 的文档,但我找不到任何告诉我页面变量在去using 变量所在函数中的另一个函数。
此外,有时代码能够计算函数的某些表达式,但通常会在第三个时失败。但是,如果我一步步调试 运行 ,它总是在第一行失败。这就是让我相信这是一个处理问题的原因。
对于任何想知道为什么我不直接从 browser 和 page 变量中删除 using 并自行处理它们的人,我有两个原因。第一,我没有处置非托管代码的经验,当我尝试将处置添加到 finalizer/destructor 时它不起作用,其次,我不想编写代码来完成该语言已经完成的工作对我来说。
问题是使用 Action 而不是 Func。
行动总是returns无效。由于调用的函数 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();
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 的文档,但我找不到任何告诉我页面变量在去using 变量所在函数中的另一个函数。
此外,有时代码能够计算函数的某些表达式,但通常会在第三个时失败。但是,如果我一步步调试 运行 ,它总是在第一行失败。这就是让我相信这是一个处理问题的原因。
对于任何想知道为什么我不直接从 browser 和 page 变量中删除 using 并自行处理它们的人,我有两个原因。第一,我没有处置非托管代码的经验,当我尝试将处置添加到 finalizer/destructor 时它不起作用,其次,我不想编写代码来完成该语言已经完成的工作对我来说。
问题是使用 Action 而不是 Func
行动总是returns无效。由于调用的函数 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();