当你有一个按钮,并执行以下操作:
Private Function Button_OnClick
Button.Enabled = False
[LONG OPERATION]
End Function
Run Code Online (Sandbox Code Playgroud)
然后该按钮不会变灰,因为长操作会阻止UI线程重新绘制控件.我知道正确的设计是启动后台线程/调度程序,但有时这对于简单的操作来说太麻烦了.
那么如何强制按钮在禁用状态下重绘?我在Button上尝试了.UpdateLayout(),但它没有任何效果.我也尝试过使用WinForms时通常可以正常工作的System.Windows.Forms.DoEvents(),但它也没有效果.
最近,我不得不在我的PCL ListView上实现无限滚动/延迟加载.我将遗漏大部分代码,但最重要的部分是:
视图模型
var countries = // get countries
foreach (var country in countries)
{
// Countries is an ObservableCollection<Country>
Countries.Add(country);
}
Run Code Online (Sandbox Code Playgroud)
这似乎在Android上运行良好,但在iOS上,我不断超出范围异常,特别是当我快速滚动列表时.我的修复是在主UI线程中运行此代码.
// wrap the code with this
Device.BeginInvokeOnMainThread(async () => {});
Run Code Online (Sandbox Code Playgroud)
我现在的问题是,所有查看更新或设置可观察集合的模型服务调用是否应始终在UI线程中执行?
我有几个命令设置 Countries.没有UI线程块,它们似乎工作正常.我只有如上所述添加项目的问题.
是否应始终在UI线程中设置和更新ObservableCollection?
这是我遇到的问题:我需要确保在UI线程上实例化一个对象.如果不是,它应该抛出异常.但是如何检查方法内部是否在UI线程上运行?注意:我不想将任何信息传递给对象的构造函数.
完美的候选者将是DispatcherSynchronizationContext(SynchronizationContext的WPF实现),它在内部持有对Dispatcher的引用,Dispatcher引用与之关联的线程,但遗憾的是该字段是私有的,因此我无法访问它.
基本上,我试图运行一个秒计数器和一个水平计数器.每10秒我想要++级别.
但是那还没有实现,到目前为止我只是试图让秒显示但是我得到运行时异常和崩溃.
谷歌搜索我看到它,因为我试图从我的线程更新UI,这是不允许的.所以我想我将需要asyncTask,但我不知道如何用我简单的小程序做到这一点.请帮忙或给我一些替代方案......
package com.ryan1;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class main extends Activity {
int level = 1;
int seconds_running=0;
TextView the_seconds;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
the_seconds = (TextView) findViewById(R.id.textview_seconds);
Thread thread1 = new Thread(){
public void run(){
try {
sleep(1000); Log.d("RYAN", " RYAN ");
updated_secs();
} catch (Exception e) {
e.printStackTrace();
Log.d("RYAN", " "+e);
}
}
};
thread1.start();
}
public void updated_secs(){
seconds_running++;
the_seconds.setText(" "+seconds_running);
}
}
Run Code Online (Sandbox Code Playgroud) 我的应用程序使用异步HttpWebRequest请求预取大量视频帧.因此,如果有100帧,预取器将异步请求所有100帧,一次全部请求,并在收到时进行处理.即它同时进行100次异步调用.这可能会使网卡饱和,但没关系.我想最大化网络带宽.
但是,当发生此预取时,用户可能想要查看其中一个帧.因此,假设他们想要查看第56帧.问题是,帧1 - 100已经被请求,并且在管道中,因此对帧56的请求可能需要很长时间才能得到响应.
如果有一些方法可以在完成asynch请求之后重新确定它们的优先级,那会更好.并将用户请求推送到队列的前面.
如果我不能这样做,我想我必须批量请求帧,以便我可以在批次之间插入我的用户请求,并避免超时.
关于如何正确设计这一点的任何想法都将非常感激.
我正在尝试遵循Android最佳做法,因此在调试模式下,我将打开以下所有内容:
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); //detect and log all thread violations
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build()); //detect and log all virtual machine violations
Run Code Online (Sandbox Code Playgroud)
当我尝试在主(UI)线程中使用任何类型的文件访问或SQL时,Android现在对我大喊大叫.但我看到很多建议在主线程中使用文件访问和/或SQL.例如,主活动应该在内部加载默认首选项值onCreate(),以防它们尚未设置:
PreferenceManager.setDefaultValues(context, resId, readAgain);
Run Code Online (Sandbox Code Playgroud)
糟糕 - 导致第一次应用程序执行时的文件访问,因为onCreate()在UI线程上调用.我能看到的唯一方法是启动一个单独的线程---它引入了一个竞争条件和其他可能读取偏好的UI代码,并期望已经设置了默认值.
还要考虑DownloadManager等服务.(实际上,它是如此错误,以至于它在现实生活中无用,但让我们假装它可以工作一秒钟.)如果你排队下载,你会得到一个事件(在主线程上)告诉你下载已经完成.要实际获取有关该下载的信息(它只提供下载ID),您必须查询涉及游标的DownloadManager ---如果您启用了严格的策略,则会出错.
那么故事是什么 - 在主线程中访问游标是否可以?或者这是一件坏事,Android开发团队和Android书籍作者中有一半忘记了这一点?
我们正在使用WinForms(3.5)构建.NET应用程序.
我最近添加了一个新功能,并在访问某些控件时开始遇到奇怪的行为.问题是某些UI控件访问只是暂停执行(没有看到异常).
仔细检查(使用WinDbg)我意识到控件是从ThreadPool线程更新的,并且抛出了CrossThreadMessagingException.
我的问题是 - 有关如何规避这种行为的良好做法吗?
这将是非常麻烦的,但也许不可能围绕使用Control.Invoke方法访问UI控件的每个代码位置.
我如何将我的代码划分为不应该使用Invoke的"安全"代码?
我需要在循环中添加大量视图,而这个片段就是这样,应用程序还将有一个导航抽屉和操作栏,用户可以在其中执行操作.
所以我希望这个过程不会a)通过阻止用户来减慢app的速度,b)最好在后台线程中添加视图.
困境是我认为android不喜欢在非UI线程中添加视图,所以有最佳实践吗?我计划在片段视图中显示进度条视图对象,而其余视图是使用addView和相关计算生成的
我刚回答了一个关于是否Task可以更新UI的问题.当我玩我的代码时,我意识到我不清楚自己的一些事情.
如果我有一个带有一个控件的窗体txtHello,我可以从任务更新UI,看起来,如果我立即执行它Task.Run:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Task.Run(() =>
{
txtHello.Text = "Hello";
});
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我Thread.Sleep甚至5毫秒,CrossThread则抛出预期的错误:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Task.Run(() =>
{
Thread.Sleep(5);
txtHello.Text = "Hello"; //kaboom
});
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定为什么会这样.对于极短的运行,是否有某种优化Task?
从后台线程,当UI需要更新时,需要使用async(execute:)函数发布到DispatchQueue.main,如下所示:
static func executeInUIThread(_ uiThreadFunc: @escaping (Any?) -> Void, _ parms: Any?) {
DispatchQueue.main.async {
// Update UI
uiThreadFunc(parms)
}
}
Run Code Online (Sandbox Code Playgroud)
可以访问闭包内部的uiThreadFuncand ,因为闭包从其“周围上下文”捕获变量。parms
但可以说,我不喜欢 lambda 风格(在 swift 中称为闭包)编程。我怎样才能在不关闭的情况下做到这一点?
我尝试了以下操作:
static func executeInUIThread(_ uiThreadFunc: @escaping (Any?) -> Void, _ parms: Any?) {
let workItem = DispatchWorkItem(block: EventLoopMgr.InternalExecuteInUIThread)
DispatchQueue.main.async(execute: workItem)
}
private static func InternalExecuteInUIThread() {
// How to execute the uiThreadfunc? This block doesn't take any parameters.
}
Run Code Online (Sandbox Code Playgroud)
它不起作用,因为初始化 DispatchWorkItem 时的块不带参数。因此,我无法通过uiThreadFunc …