Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading Device.BeginInvokeMainThread用于什么?_Multithreading_Xamarin_Xamarin.forms - Fatal编程技术网

Multithreading Device.BeginInvokeMainThread用于什么?

Multithreading Device.BeginInvokeMainThread用于什么?,multithreading,xamarin,xamarin.forms,Multithreading,Xamarin,Xamarin.forms,我想有人向我解释什么是Device.beginInvokeMainThread,它是用来做什么的 还有一些使用它的示例。您只能从主UI线程更新UI。如果您正在后台线程上运行代码,并且需要更新UI,BeginInvokeOnMainThread()允许您强制代码在主线程上运行,以便您可以更新UI。仅添加一个示例 假设您有一个异步方法DoAnyWorkAsync,如果您这样调用它(作为示例): DoAnyWorkAsync().ContinueWith ((arg) => {

我想有人向我解释什么是Device.beginInvokeMainThread,它是用来做什么的


还有一些使用它的示例。

您只能从主UI线程更新UI。如果您正在后台线程上运行代码,并且需要更新UI,
BeginInvokeOnMainThread()
允许您强制代码在主线程上运行,以便您可以更新UI。

仅添加一个示例

假设您有一个异步方法
DoAnyWorkAsync
,如果您这样调用它(作为示例):

 DoAnyWorkAsync().ContinueWith ((arg) => {
                StatusLabel.Text = "Async operation completed...";
            });
StatusLabel
是XAML中的标签

异步操作完成后,上面的代码将不会在标签中显示消息,因为回调位于与UI线程不同的另一个线程中,因此它无法修改UI

如果您更新了同一代码,只需将
StatusLabel
文本更新包含在
Device.beginInvokeMainThread
中,如下所示:

 DoAnyWorkAsync().ContinueWith ((arg) => {
     Device.BeginInvokeOnMainThread (() => {
                StatusLabel.Text = "Async operation completed...";
           });
     });
不会有任何问题


你自己试试看,用
Task.Delay(2000)
替换
DoAnyWorkAsync()
简单的答案是:后台线程无法修改UI元素,因为iOS和Android中的大多数UI操作都不是线程安全的;因此,您需要调用UI线程来执行修改UI的代码,例如MyLabel.Text=“New Text”

详细答案可在Xamarin文档中找到:

对于iOS:

IOSPlatformServices.BeginInvokeMainThread()方法只调用nsrunlop.Main.BeginInvokeMainThread

public void BeginInvokeOnMainThread(Action action)
{
    NSRunLoop.Main.BeginInvokeOnMainThread(action.Invoke);
}

从线程使用此方法调用指定对象中的代码,该对象在UI线程中使用指定选择器公开这是影响UIKit或AppKit的大多数操作所必需的,因为这些API都不是线程安全的。

当主线程返回其主循环处理事件时,将执行该代码

对于Android:

许多人认为Xamarin.Android BeginInvokeOnMainThread()方法使用Activity.runOnUiThread(),但事实并非如此,使用runOnUiThread()和Handler.Post()之间存在差异:


如您所见,Handler.Post(action)不会立即执行操作代码。它被添加到循环器的消息队列中,并在UI线程计划处理其消息时进行处理

如上所述,任何UI更新都必须在主线程中进行,否则将发生导出


虽然Xamarin.Forms有一个特点,但只要用户界面的这一部分与当前显示的用户界面元素分离,就可以在主线程下操纵用户界面元素(例如创建
标签
s并将其添加到
堆栈布局
子类
集合),而不会出现任何故障。这种方法可以通过创建Xamarin.Forms控件并在单独的线程中设置它们在内存中/屏幕外的子/子关系来提高性能,但要将它们附加到显示的容器(例如,分配
ContentPage
内容
属性)您必须在
设备中执行此操作。BeginInvokeOnMainThread()

非常感谢您。我们想在发布后指出android实现的新位置,并在github repo下搜索
IPlatformServices
,查找其他平台实现
public final void runOnUiThread(Runnable action) {
    if (Thread.currentThread() != mUiThread) {
        mHandler.post(action);//<-- post message delays action until UI thread is scheduled to handle messages
    } else {
        action.run();//<--action is executed immediately if current running thread is UI thread. 
    }
}
public void BeginInvokeOnMainThread(Action action)
{
    if (s_handler == null || s_handler.Looper != Looper.MainLooper)
    {
        s_handler = new Handler(Looper.MainLooper);
    }

    s_handler.Post(action);
}