gpt4 book ai didi

c# - 异步等待线程完成

转载 作者:行者123 更新时间:2023-12-02 08:31:01 25 4
gpt4 key购买 nike

嗯,我有一个从电脑上截取屏幕截图的函数,但不幸的是它阻塞了主 UI,所以我决定对其进行异步[线程调用];但是,我发现在返回之前等待线程结果时遇到麻烦位图。

这是我的代码:

/// <summary>
/// Asynchronously uses the snapshot method to get a shot from the screen.
/// </summary>
/// <returns> A snapshot from the screen.</returns>
private Bitmap SnapshotAsync()
{
Bitmap image = null;
new Thread(() => image = Snapshot()).Start();

while (image == null)
{
new Thread(() => Thread.Sleep(500)).Start(); //Here i create new thread to wait but i don't think this is a good way at all.
}
return image;
}

/// <summary>
/// Takes a screen shots from the computer.
/// </summary>
/// <returns> A snapshot from the screen.</returns>
private Bitmap Snapshot()
{
var sx = Screen.PrimaryScreen.Bounds.Width;
var sy = Screen.PrimaryScreen.Bounds.Height;
var shot = new Bitmap(sx, sy, PixelFormat.Format32bppArgb);
var gfx = Graphics.FromImage(shot);
gfx.CopyFromScreen(0, 0, 0, 0, new Size(sx, sy));
return shot;
}

虽然上面的方法是按照我想要的方式异步工作的,但我相信它可以改进。特别是我执行数百个线程来等待结果的方式,我确信这种方式不好。

所以我真的需要任何人看看代码并告诉我如何改进它。

[注意我正在使用 .NET 3.5]

提前致谢。

在 Eve 和 SiLo 的帮助下解决的问题是最好的 2 个答案

  • 1 :
>     private void TakeScreenshot_Click(object sender, EventArgs e)
> {
> TakeScreenshotAsync(OnScreenshotTaken);
> }
>
> private static void OnScreenshotTaken(Bitmap screenshot)
> {
> using (screenshot)
> screenshot.Save("screenshot.png", ImageFormat.Png);
> }
>
> private static void TakeScreenshotAsync(Action<Bitmap> callback)
> {
> var screenRect = Screen.PrimaryScreen.Bounds;
> TakeScreenshotAsync(screenRect, callback);
> }
>
> private static void TakeScreenshotAsync(Rectangle bounds, Action<Bitmap> callback)
> {
> var screenshot = new Bitmap(bounds.Width, bounds.Height,
> PixelFormat.Format32bppArgb);
>
> ThreadPool.QueueUserWorkItem((state) =>
> {
> using (var g = Graphics.FromImage(screenshot))
> g.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size);
>
> if (callback != null)
> callback(screenshot);
> });
> }
  • 2 :
>     void SnapshotAsync(Action<Bitmap> callback)
> {
> new Thread(Snapshot) {IsBackground = true}.Start(callback);
> }

>     void Snapshot(object callback)
> {
> var action = callback as Action<Bitmap>;
> var sx = Screen.PrimaryScreen.Bounds.Width;
> var sy = Screen.PrimaryScreen.Bounds.Height;
> var shot = new Bitmap(sx, sy, PixelFormat.Format32bppArgb);
> var gfx = Graphics.FromImage(shot);
> gfx.CopyFromScreen(0, 0, 0, 0, new Size(sx, sy));
> action(shot);
> }

Usage, for example, through a button's click:

void button1_Click(object sender, EventArgs e)
{
SnapshotAsync(bitmap => MessageBox.Show("Copy successful!"));
}

最佳答案

async/await 关键字完全符合您的要求,非常优雅。

以下是我如何将您的方法转换为正确的模式:

private static async Task<Bitmap> TakeScreenshotAsync()
{
var screenRect = Screen.PrimaryScreen.Bounds;
return await TakeScreenshotAsync(screenRect);
}

private static async Task<Bitmap> TakeScreenshotAsync(Rectangle bounds)
{
var screenShot = new Bitmap(bounds.Width, bounds.Height,
PixelFormat.Format32bppArgb);

// This executes on a ThreadPool thread asynchronously!
await Task.Run(() =>
{
using (var g = Graphics.FromImage(screenShot))
g.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size);

});

return screenShot;
}

然后你会做这样的事情:

private async void TakeScreenshot_Click(object sender, EventArgs e)
{
var button = sender as Button;
if(button == null) return;

button.Enabled = false;
button.Text = "Screenshoting...";

var bitmap = await TakeScreenshotAsync();
bitmap.Save("screenshot.png", ImageFormat.Png);

button.Text = "Take Screenshot";
button.Enabled = true;
}

关于c# - 异步等待线程完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14299209/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com