c#线程位图
本文关键字:位图 线程 | 更新日期: 2023-09-27 18:04:14
我想知道如果不是线程中的void函数,我可以传递位图函数。当我传递无效函数时,没有错误报告,但当我传递位图函数时,我得到一个错误。下面是代码:
protected void btnSubmit_Click(object sender, EventArgs e)
{
Thread thr = new Thread(new ThreadStart(OptimizeWebBrowser));
thr.SetApartmentState(ApartmentState.STA);
thr.Start();
}
public System.Drawing.Bitmap CaptureWebPage(string url)
{
System.Windows.Forms.WebBrowser browser = new System.Windows.Forms.WebBrowser();
browser.ScrollBarsEnabled = false;
browser.ScriptErrorsSuppressed = true;
browser.Navigate(url);
while (browser.ReadyState != WebBrowserReadyState.Complete)
System.Windows.Forms.Application.DoEvents();
System.Threading.Thread.Sleep(1500);
int width = browser.Document.Body.ScrollRectangle.Width;
int height = browser.Document.Body.ScrollRectangle.Height;
browser.Width = width;
browser.Height = height;
System.Drawing.Bitmap bmp = new Bitmap(width, height);
browser.DrawToBitmap(bmp, new System.Drawing.Rectangle(0, 0, width, height));
return bmp;
}
protected void OptimizeWebBrowser()
{
System.Windows.Forms.WebBrowser browser = new System.Windows.Forms.WebBrowser();
browser.ScrollBarsEnabled = false;
browser.ScriptErrorsSuppressed = true;
browser.Navigate(currentPageUrl);
while (browser.ReadyState != WebBrowserReadyState.Complete)
System.Windows.Forms.Application.DoEvents();
System.Threading.Thread.Sleep(1500);
int width = browser.Document.Body.ScrollRectangle.Width;
int height = browser.Document.Body.ScrollRectangle.Height;
browser.Width = width;
browser.Height = height;
System.Drawing.Bitmap bmp = new Bitmap(width, height);
browser.DrawToBitmap(bmp, new System.Drawing.Rectangle(0, 0, width, height));
Response.ContentType = "image/jpeg";
Response.AppendHeader("Content-Disposition", "attachment; filename=screenshot.jpg");
bmp.Save(Response.OutputStream, ImageFormat.Jpeg);
bmp.Dispose();
bmp.Dispose();
Response.End();
}
当我现在试图把capture网页而不是OptimizeWebBrowser在ThreadStart,我得到一个错误:'没有超载' capture网页'匹配委托'System.Threading.ThreadStart'。
要将参数传递给线程,您应该使用ParameterizedThreadStart
委托,该委托具有object
类型的单个参数。所以你应该像下面这样使用它:
System.Drawing.Bitmap bitmapObject;
private static readonly bitmapLock = new object();
// change parameter type to object and int he method just cast it to string
public void CaptureWebPage(object rawUrl)
{
string url = rawUrl.ToString();
lock(bitmapLock)
{
// create a bitmap object
bitmapObject = ...;
}
}
// start thread
Thread thr = new Thread(CaptureWebPage);
thr.Start("url");
PS:你发布的代码很难阅读,考虑一些代码重构和样式更改
还没有机会尝试这个,但是out关键字可能有效。将位图设置为函数的参数(将其保持为void函数),并在使用ParameterizedThreadStart创建threadstart时传递一个。由于out关键字在函数声明中,当函数完成时将返回该值。
如果不是,我建议你输出的位图是一个全局变量,你可以从任何一个线程访问。您可以像往常一样访问它,但我建议使用lock()关键字以防万一。
此外,c#中的BackgroundWorker类允许您在线程完成时通过向RunWorkerCompleted事件添加一个函数来获得返回结果
不行,不能传递有返回值的方法。由于ThreadStart
方法不等待线程完成,因此从线程返回任何东西都没有意义,因为没有任何东西等待结果。
请注意,您的代码将永远不能可靠地工作,因为响应可能在您的代码完成之前结束(这称为竞争条件)。你应该研究一下IAsyncHttpHandler的用法。
但是,为了将来的参考,如果没有竞争条件,这就是如何解决这个问题的。
你需要使用上下文对象。首先,您需要声明一个类,其中包含该方法所需的所有信息(以及它的返回值,或者更理想的是,当结果准备好时要做的事情——也就是委托)。例如:
class CaptureWebPageContext
{
public string Url;
public Action<Bitmap> ResultDelegate;
}
一旦你有了这个,你可以初始化它并将它发送给void (object)
委托(ParameterizedThreadStart
):
var context = new CaptureWebPageContext() { Url = url, ResultDelegate = BitmapRendered };
var thr = new Thread(context);
thr.Start(context);
protected void BitmapRendered(Bitmap result)
{
// ... Do stuff with the final bitmap.
}
protected void CaptureWebPage(object contextObject)
{
var context = (CaptureWebPageContext)contextObject;
var url = context.Url;
//... Your code to capture the web page.
context.ResultDelegate(bmp);
bmp.Dispose();
}
理想情况下,你会使用。net异步模式,但我看到你需要一个STA线程