c#线程位图

c#线程位图,c#,asp.net,multithreading,C#,Asp.net,Multithreading,我想知道我是否可以传递位图函数而不是线程中的void函数。 当我传递void函数时,没有报告错误,但是当我传递位图函数时,我得到一个错误。 代码如下: protected void btnSubmit_Click(object sender, EventArgs e) { Thread thr = new Thread(new ThreadStart(OptimizeWebBrowser)); thr.SetApartmentState(ApartmentState.STA); thr.St

我想知道我是否可以传递位图函数而不是线程中的void函数。 当我传递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();     
}

当我现在尝试将CAptureWebPage而不是OptimizeWebBrowser放在ThreadStart中时,我收到一个错误:“CaptureWebPage”的重载与委托“System.Threading.ThreadStart”匹配。

要将参数传递给线程,您应该使用
ParameterizedThreadStart
委托,该委托有一个
对象
类型的参数。因此,您应该使用它,如下所示:

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:你发布的代码很难阅读,考虑一些代码重构和样式改变

没有机会尝试这个,但是关键字可能起作用。将位图设置为函数的参数(将其保留为void函数),并在使用ParameterizedThreadStart创建threadstart时传入一个。由于out关键字在函数声明中,因此函数完成时将返回该值

如果不是,我建议将输出的位图设置为全局变量,您可以从任一线程访问。虽然我建议使用lock()关键字以防万一,但您可以像平常一样访问它


此外,c#中的BackgroundWorker类允许您在线程完成时通过向事件添加函数来获得返回结果。不,您不能传递具有返回值的方法。由于
ThreadStart
方法不等待线程完成,因此从线程返回任何内容都没有意义,因为没有任何内容等待结果


有几种方法可以从线程返回数据,例如在声明方法的类中使用成员变量,但棘手的是,启动线程后不会立即得到结果,因此必须等待。通常,您会使用一种回调方法,线程可以在数据准备好使用时调用该方法。

请注意,您的代码永远不会可靠地工作,,因为响应可能在代码完成之前结束(这称为竞争条件)。你应该调查一下这个词的用法

然而,作为将来的参考,如果没有比赛条件的话,这就是你解决这个问题的方法

您需要使用上下文对象。首先,您需要声明一个类,该类包含该方法所需的所有信息(以及它的返回值,或者更理想的情况是,当结果准备好时要做的事情,也称为委托)。例如:


理想情况下,您可以使用.Net异步模式,但我发现您需要一个STA线程。

我认为Laziale希望传入一个函数,该函数返回一个位图作为他的ThreadStart,而编译器正在努力解决这个问题,因为ThreadStart委托是无效的。是的,谢谢Nick。这就是我要找的。这可能吗?开场白:谢谢古尔法,你有没有一个例子的链接,我可以看看它是如何完成的。谢谢Hanks Jonathan,这是我在线程方面遇到的问题之一。在新的线程中没有响应,因此我不会在最后保存任何jpeg文件。我去查一下iAsyncHttpHandler,也许会有帮助。再来一次
class CaptureWebPageContext
{
    public string Url;
    public Action<Bitmap> ResultDelegate;
}
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();
}