سؤال

في تطبيق WPF الخاص بي ، أقوم ببعض الاتصالات غير المتزامنة (مع الخادم). في وظيفة رد الاتصال ، انتهى بي الأمر إلى إنشاء كائنات inkpresenter من النتيجة من الخادم. يتطلب هذا أن يكون موضوع الجري STA ، وهو ما يبدو أنه ليس كذلك حاليًا. لذلك أحصل على الاستثناء التالي:

لا يمكن إنشاء مثيل "inkpresenter" المحدد في التجميع [..] يجب أن يكون مؤشر ترابط الاتصال STA ، لأن العديد من مكونات واجهة المستخدم تتطلب ذلك.

حاليا مكالمة وظيفي غير متزامن مثل هذا:

public void SearchForFooAsync(string searchString)
{
    var caller = new Func<string, Foo>(_patientProxy.SearchForFoo);
    caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null);
}

كيف يمكنني جعل رد الاتصال - الذي سيؤدي إلى إنشاء Inkpresenter - STA؟ أو استدعاء XamlReader تحليل في خيط STA جديد.

public void SearchForFooCallbackMethod(IAsyncResult ar)
{
    var foo = GetFooFromAsyncResult(ar); 
    var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; // <!-- Requires STA
    [..]
}
هل كانت مفيدة؟

المحلول

يمكنك بدء تشغيل خيوط STA مثل ذلك:

    Thread thread = new Thread(MethodWhichRequiresSTA);
    thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
    thread.Start(); 
    thread.Join(); //Wait for the thread to end

المشكلة الوحيدة هي أنه يجب تمرير كائن النتائج الخاص بك بطريقة أو بأخرى .. يمكنك استخدام حقل خاص لذلك ، أو الغوص في نقل المعلمات إلى مؤشرات الترابط. هنا قمت بتعيين بيانات FOO في حقل خاص وبدء تشغيل مؤشر ترابط STA لتحفيز Inkpresenter!

private var foo;
public void SearchForFooCallbackMethod(IAsyncResult ar)
{
    foo = GetFooFromAsyncResult(ar); 
    Thread thread = new Thread(ProcessInkPresenter);
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    thread.Join(); 
}

private void ProcessInkPresenter()
{
    var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter;
}

أتمنى أن يساعدك هذا!

نصائح أخرى

يمكنك استعمال ال دبلاتش فئة لتنفيذ طريقة استدعاء على واجهة المستخدم. يوفر المرسل خاصية ثابتة CurrentDispatcher للحصول على مرسل الخيط.

إذا تم إنشاء كائن الفصل الخاص بك ، الذي ينشئ inkpresenter ، على Throad ، فإن طريقة CurrentDispatcher تُرجع المرسل الخاص بـ U-throad.

على المرسل ، يمكنك الاتصال بـ BeginInvoke Method للاتصال بالمندوب المحدد بشكل غير متزامن على الخيط.

يجب أن يكون جيدًا بما يكفي لاستدعاؤه على موضوع واجهة المستخدم. لذلك ، استخدم أ BackgroundWorker وعلى RunWorkerAsyncCompleted, ، يمكنك بعد ذلك القيام بإنشاء Inkpresenter.

إنه جزء من الاختراق ، لكنني سأستخدمه Xtatestrunner لذلك سيبدو الرمز الخاص بك:

    public void SearchForFooAsync(string searchString)
    {
        var caller = new Func<string, Foo>(_patientProxy.SearchForFoo);
        caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null);
    }

    public void SearchForFooCallbackMethod(IAsyncResult ar)
    {

            var foo = GetFooFromAsyncResult(ar); 
InkPresenter inkPresenter;
            new XTATestRunner().RunSTA(() => {
                        inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter;
                    });
    }

كمكافأة ، من الممكن التقاط استثناءات تم إلقاؤها في موضوع STA (أو MTA) مثل هذا:

try{
new XTATestRunner().RunSTA(() => {
                        throw new InvalidOperationException();
                    });
}
catch(InvalidOperationException ex){
}

لقد استخدمت للتو ما يلي للحصول على محتوى الحافظة من سلسلة STA. اعتقدت أنني سأقوم بنشره لمساعدة شخص ما في المستقبل ...

string clipContent = null;
Thread t = new Thread(
    () =>
    {
        clipContent = Clipboard.GetText();
    });
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();

// do stuff with clipContent

t.Abort();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top