2011-08-01 38 views
0

我想知道如果不是線程中的void函數,我可以通過位圖函數。 當我傳遞void函數時沒有錯誤報告,但是當我傳遞位圖函數時出現錯誤。 下面是代碼:c#線程位圖

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();  
} 

當我現在想在的ThreadStart把CAptureWebPage而不是OptimizeWebBrowser,我得到一個錯誤:「不超載的‘CaptureWebPage’匹配委託‘System.Threading.ThreadStart’ 。

+0

序幕:http://stackoverflow.com/q/6895856/60761 –

回答

0

要傳遞一個參數到一個線程,你應該使用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:您已經發布代碼是非常難以閱讀,考慮一些代碼重構和樣式改變

+1

我覺得Laziale希望在返回一個位圖作爲自己的ThreadStart一個函數時,和與會代表的ThreadStart是空洞的編譯器與掙扎。 –

+0

是的,謝謝尼克。這就是我正在尋找的。那可能嗎? – Laziale

+0

我已經更新了我的答案,現在更清楚了嗎? – sll

0

還沒有機會嘗試這個,但out關鍵字可能會起作用。將位圖設置爲函數的參數(將其保留爲void函數),並在通過使用ParameterizedThreadStart創建threadstart時傳遞一個參數。由於out關鍵字位於函數聲明中,因此函數完成時將返回該值。

如果不是,我會建議讓您輸出的位圖是一個全局變量,您可以從任一線程訪問它。這可以像你通常那樣訪問,儘管我會建議使用lock()關鍵字以防萬一。

此外,在C#中的BackgroundWorker類可以讓你得到一個返回結果的線程是通過添加一個函數來RunWorkerCompleted事件

0

沒有完成時,你不能傳遞具有返回值的方法。因爲ThreadStart方法不等待線程完成,所以從線程返回任何內容都沒有意義,因爲沒有任何內容等待結果。

有幾種從線程返回數據的方法,例如在聲明方法的類中使用成員變量,但棘手的部分是在啓動線程後不會立即得到結果,所以你必須等待它。通常,您可以使用線程可以在數據準備好使用時調用的回調方法。

+0

謝謝古爾法,你有鏈接的例子,我可以檢查它是如何完成的。謝謝 – Laziale

0

請注意,您的代碼將無法可靠地運行,因爲響應可能會在代碼完成之前結束(這稱爲競爭條件)。您應該調查使用IAsyncHttpHandler

但是,爲了將來的參考,這是如果你沒有競爭條件,你將如何解決這個問題。

您需要使用上下文對象。首先,您需要聲明一個包含該方法所需的所有信息的類(以及它的返回值,或者更理想的是當結果準備就緒時--a.k.a.代表)。例如: -

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(); 
} 

理想情況下,你會使用。網絡異步模式,但我看到你需要一個STA線程。

+0

謝謝喬納森,這是我與線程有問題之一。新線程沒有響應,因此我沒有得到任何jpeg文件來保存結尾。我會檢查iAsyncHttpHandler,這可能會有所幫助。 Thx再一次 – Laziale