เธรดการโทรต้องเป็น STA เนื่องจากส่วนประกอบ UI จำนวนมากต้องการสิ่งนี้


174

ฉันใช้http://www.codeproject.com/KB/IP/Facebook_API.aspx

ฉันพยายามที่จะเรียกXAMLซึ่งสร้างขึ้นโดยใช้WPF แต่มันทำให้ฉันมีข้อผิดพลาด:

เธรดการโทรต้องเป็น STA เนื่องจากส่วนประกอบ UI จำนวนมากต้องการสิ่งนี้

ผมไม่ทราบว่าจะทำอย่างไร. ฉันพยายามทำสิ่งนี้:

FacebookApplication.FacebookFriendsList ffl = new FacebookFriendsList();

แต่มันทำให้ฉันมีข้อผิดพลาด

ฉันเพิ่มผู้ทำงานเบื้องหลัง:

static BackgroundWorker bw = new BackgroundWorker();

static void Main(string[] args)
{
    bw.DoWork += bw_DoWork;
    bw.RunWorkerAsync("Message to worker");
    Console.ReadLine();
}

static void bw_DoWork(object sender, DoWorkEventArgs e)
{
    // This is called on the worker thread
    FacebookApplication.FacebookFriendsList ffl = new FacebookFriendsList();

    Console.WriteLine(e.Argument);        // Writes "Message to worker"

    // Perform time-consuming task...
}

คำตอบ:


222

ลองเรียกใช้รหัสของคุณจากโปรแกรมเลือกจ่ายงาน :

Application.Current.Dispatcher.Invoke((Action)delegate{
      // your code
});

ใช่แล้วพวกคุณช่วยชีวิตฉันไว้ !!
Alex McManns

11
นี่คือคำตอบที่แท้จริง คุณสามารถแฮ็คออกไปที่ความโง่เขลาของหน้าต่าง WPF ด้วยสิ่งนี้
Andrew

7
เช่นเดียวกับกรณีนี้หากคุณใช้ MVVMLight คุณสามารถใช้งานได้DispatcherHelper.CheckBeginInvokeOnUI(Action action)
TimothyP

ปัญหานี้ดูซับซ้อนและผิดหวัง แต่ภาพนี้ช่างยอดเยี่ยม ขอบคุณมาก !
Kay Lee

4
@Andrew มันไม่ใช่ความโง่เขลาคุณเพียงแค่พยายามเข้าถึงเธรด UI จากเธรดพื้นหลัง
Krusty

139

หากคุณทำการโทรจากเธรดหลักคุณต้องเพิ่มแอ็ตทริบิวต์ STAThread ให้กับเมธอด Main ดังที่ระบุไว้ในคำตอบก่อนหน้า

หากคุณใช้เธรดแยกต่างหากเธรดจะต้องอยู่ใน STA (อพาร์ทเมนต์แบบเธรดเดียว) ซึ่งไม่ใช่กรณีของเธรดผู้ทำงานเบื้องหลัง คุณต้องสร้างชุดข้อความด้วยตนเองดังนี้:

Thread t = new Thread(ThreadProc);
t.SetApartmentState(ApartmentState.STA);

t.Start();

กับ ThreadProc เป็นผู้รับมอบสิทธิ์ชนิด ThreadStart


2
สามารถ (โดยใช้ STA) นี้สามารถมีผลข้างเคียงหรือไม่?
Louis Rhys

10
ผลข้างเคียงหลักของการเป็น STA คือการเรียกกลับ COM พร้อมกันจะต่อเนื่องกัน หากคุณไม่ได้ใช้การโทรกลับ COM มันไม่สำคัญ
Timores

ช่วยชีวิตฉันไว้! สามารถใช้สิ่งนี้ได้ในแอพ WPF ที่โฮสต์ API ท้องถิ่นสำหรับการรวมระหว่างสองแอพที่ต่างกัน
schizoid04

18

คุณสามารถลองสิ่งนี้

// create a thread  
Thread newWindowThread = new Thread(new ThreadStart(() =>  
{  
    // create and show the window
    FaxImageLoad obj = new FaxImageLoad(destination);  
    obj.Show();  

    // start the Dispatcher processing  
    System.Windows.Threading.Dispatcher.Run();  
}));  

// set the apartment state  
newWindowThread.SetApartmentState(ApartmentState.STA);  

// make the thread a background thread  
newWindowThread.IsBackground = true;  

// start the thread  
newWindowThread.Start();  

ขอบคุณ สิ่งนี้จะช่วยเมื่อใช้คลาส Applicationcontext แทนแบบฟอร์ม
SaddamBinSyed

ฉันกำลังเปิดฟอร์มใหม่เมื่อมีการคลิกปุ่มเหมือนที่ฉันทำในที่อื่น ๆ ความคิดใดที่ว่าทำไมหนึ่งในสถานที่เหล่านั้นกำลังโยนข้อผิดพลาดนี้
Paul McCarthy

17

ฉันสงสัยว่าคุณได้รับการติดต่อกลับไปยังองค์ประกอบ UI จากเธรดพื้นหลัง ฉันขอแนะนำให้คุณโทรออกโดยใช้ BackgroundWorker เนื่องจากเป็นเธรด UI ที่ทราบ

สำหรับ BackgroundWorker โปรแกรมหลักควรถูกทำเครื่องหมายเป็น [STAThread]


1
ฉันลองเพิ่มตามข้างต้น แต่ก็ยังให้ข้อผิดพลาด: /
C. ..

ฉันไม่ใช่ familliar ที่มีรหัส คุณสามารถตรวจแก้จุดบกพร่องและค้นหาบรรทัดของรหัสที่ทำให้เกิดสิ่งนี้ได้หรือไม่
Preet Sangha

3

เพียงทำเครื่องหมายโปรแกรมของคุณด้วย[STAThread]แอตทริบิวต์และข้อผิดพลาดจะหายไป! มันวิเศษ :)


1

สำหรับฉันข้อผิดพลาดนี้เกิดขึ้นเนื่องจากมีการส่งผ่านพารามิเตอร์ Null การตรวจสอบค่าตัวแปรแก้ไขปัญหาของฉันโดยไม่ต้องเปลี่ยนรหัส ฉันใช้ BackgroundWorker


-3

ถ้าคุณเรียกคำสั่ง UI หน้าต่างใหม่ในเธรดที่มีอยู่มันจะพ่นข้อผิดพลาด แทนที่จะสร้างเธรดใหม่ภายในเธรดหลักและเขียนคำสั่ง UI ของหน้าต่างในเธรดย่อยใหม่


วิธีการเขียนกรุณาอธิบาย?
Tushar Gupta - curioustushar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.