我有一个RoutedUICommand命令,可以通过两种不同的方式触发:
ICommand.Execute按钮点击事件;<button Command="local:MainWindow.MyCommand" .../>.该命令仅由顶部窗口处理:
<Window.CommandBindings>
<CommandBinding Command="local:MainWindow.MyCommand" CanExecute="CanExecuteCommmand" Executed="CommandExecuted"/>
</Window.CommandBindings>
Run Code Online (Sandbox Code Playgroud)
第一种方法仅在窗口中存在聚焦元素时才有效.无论焦点如何,第二个总是这样.
我看着BCL的ICommand.Execute实施,发现该命令不被解雇,如果Keyboard.FocusedElement是null,那么这是由设计.我仍然质疑,因为顶层可能有一个处理程序(就像在我的情况下)仍然希望接收命令,即使应用程序没有UI焦点(例如,我可能想要ICommand.Execute从收到套接字消息时的异步任务).让它如此,我仍然不清楚为什么第二种(声明性)方法总是有效,无论焦点状态如何.
在理解WPF命令路由时我缺少什么?我敢肯定这不是一个错误,而是一个功能.
下面是代码.如果您喜欢玩它,这是完整的项目.单击第一个按钮 - 命令将被执行,因为焦点位于TextBox.点击第二个按钮 - 一切都很好.单击Clear Focus按钮.现在第一个按钮(ICommand.Execute)不执行命令,而第二个按钮()仍然执行.您需要单击TextBox以使第一个按钮再次工作,因此有一个聚焦元素.
这是一个人为的例子,但它具有现实意义.我将发布一个关于托管WinForms控件的相关问题WindowsFormsHost([EDITED] 在这里问),在这种情况下Keyboard.FocusedElement总是null在焦点在里面WindowsFormsHost(有效地杀死命令执行ICommand.Execute).
XAML代码:
<Window x:Class="WpfCommandTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCommandTest"
Title="MainWindow" Height="480" Width="640" Background="Gray">
<Window.CommandBindings>
<CommandBinding Command="local:MainWindow.MyCommand" CanExecute="CanExecuteCommmand" Executed="CommandExecuted"/>
</Window.CommandBindings>
<StackPanel Margin="20,20,20,20">
<TextBox Name="textBoxOutput" …Run Code Online (Sandbox Code Playgroud) [EDITED] 这似乎是 Framework的Application.DoEvents实现中的一个错误,我在这里报告过.在UI线程上恢复错误的同步上下文可能会严重影响像我这样的组件开发人员.赏金的目标是更多地关注这个问题,并奖励@MattSmith,他的答案帮助追踪它.
我负责通过COM互操作UserControl将基于.NET WinForms 的组件作为ActiveX暴露给传统的非托管应用程序.运行时要求是.NET 4.0 + Microsoft.Bcl.Async.
该组件被实例化并在应用程序的主要STA UI线程上使用.它的实现使用async/await,因此它期望在当前线程(即,WindowsFormsSynchronizationContext)上安装序列化同步上下文的实例.
通常,WindowsFormsSynchronizationContext设置为Application.Run,托管应用程序的消息循环运行的位置.当然,这不是非托管主机应用程序的情况,我无法控制它.当然,主机应用程序仍然有自己的经典Windows消息循环,因此序列化await延续回调应该不是问题.
但是,到目前为止我提出的解决方案都不是完美的,甚至都不能正常工作.这是一个人为的例子,其中Test方法由主机app调用:
Task testTask;
public void Test()
{
this.testTask = TestAsync();
}
async Task TestAsync()
{
Debug.Print("thread before await: {0}", Thread.CurrentThread.ManagedThreadId);
var ctx1 = SynchronizationContext.Current;
Debug.Print("ctx1: {0}", ctx1 != null? ctx1.GetType().Name: null);
if (!(ctx1 is WindowsFormsSynchronizationContext))
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
var ctx2 = SynchronizationContext.Current;
Debug.Print("ctx2: …Run Code Online (Sandbox Code Playgroud) I have a project main that contains a submodule foo. For this particular project, I would like to make a small change to foo that only applies to this particular project main.
main/
+ .git
+ main.c
+ lib/
| + bar.c
+ foo/ # My `foo` submodule
+ .git
+ config.h # The file I want to patch from `main`
+ ...
Run Code Online (Sandbox Code Playgroud)
A common solution would be to go down to my submodule, make a commit Applied …
鉴于取消令牌,我想创建一个等待它的任务,这是永远不会完成但可以取消.我需要这样的模式,IMO应该很常见:
async Task DoStuff(Task t, CancellationToken ct)
{
// t was made from TaskCompletionSource,
// both t and ct are beyond my control
Task t2 = TaskFromCancellationToken(ct);
await Task.WhenAny(t, t2);
// do stuff
}
Run Code Online (Sandbox Code Playgroud)
我到目前为止最好的想法是:
Task TaskFromCancelationToken(CancellationToken ct)
{
return Task.Delay(Timeout.Infinite, ct);
}
Run Code Online (Sandbox Code Playgroud)
是否有更好的方法来实现这种逻辑?
是否有建议的自我取消和重启任务模式?
例如,我正在研究背景拼写检查程序的API.拼写检查会话被包装为Task.每个新会话都应该取消之前的会话并等待其终止(以正确地重新使用拼写检查服务提供商等资源).
我想出了这样的事情:
class Spellchecker
{
Task pendingTask = null; // pending session
CancellationTokenSource cts = null; // CTS for pending session
// SpellcheckAsync is called by the client app
public async Task<bool> SpellcheckAsync(CancellationToken token)
{
// SpellcheckAsync can be re-entered
var previousCts = this.cts;
var newCts = CancellationTokenSource.CreateLinkedTokenSource(token);
this.cts = newCts;
if (IsPendingSession())
{
// cancel the previous session and wait for its termination
if (!previousCts.IsCancellationRequested)
previousCts.Cancel();
// this is not expected to throw
// as the …Run Code Online (Sandbox Code Playgroud) 我最近一直在处理异步等待(阅读包括Stephen和Jon最后两章在内的所有可能的文章),但我得出结论,我不知道它是否100%正确. - 因此我的问题.
由于 async只允许单词等待出现,我将async不谈.
AFAIU等待着继续.而不是编写功能(连续)代码,编写同步代码.(我想把它称为可回调代码)
因此,当编译器到达时await- 它将代码分成2个部分,并在第一部分完成后注册要执行的第二部分(我不知道为什么callback不使用该字- 这正是所做的).(同时工作 - 线程回来做其他事情).
但看看这段代码:
public async Task ProcessAsync()
{
Task<string> workTask = SimulateWork();
string st= await workTask;
//do something with st
}
public Task <string> SimulateWork()
{
return ...
}
Run Code Online (Sandbox Code Playgroud)
当线程到达时await workTask;,将方法拆分为2个部分.所以在SimulateWork完成之后 - 方法的继续:AKA://do something with st- 被执行.
一切都好
但是,如果方法是:
public async Task ProcessAsync()
{
Task<string> workTask = SimulateWork();
await workTask; //i …Run Code Online (Sandbox Code Playgroud) 难道Delay(0)总要得到内联?根据我的经验,它确实:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication
{
class Program
{
static async Task Test()
{
await Task.Yield();
Console.WriteLine("after Yield(), thread: {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Delay(0);
Console.WriteLine("after Delay(0), thread: {0}", Thread.CurrentThread.ManagedThreadId);
await Task.Delay(100);
Console.WriteLine("after Delay(100), thread: {0}", Thread.CurrentThread.ManagedThreadId);
}
static void Main(string[] args)
{
Console.WriteLine("Main thread: {0}", Thread.CurrentThread.ManagedThreadId);
Test().Wait();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个控制台应用程序,因此线程池用于继续.输出:
Main thread: 11
after Yield(), thread: 7
after Delay(0), thread: 7
after Delay(100), thread: 6
Run Code Online (Sandbox Code Playgroud) 有没有办法关闭Visual Studio中任意区域的自动格式化?
我有自动格式设置为完全按我喜欢缩进.但是,对于特定区域(特别是与创建XML文档有关的区域),我希望缩进清楚地创建正在创建的XML文档的结构,而不是创建它的C#.例如:
// Format this normally.
public void WriteXMLDocument() {
// ...
using (XmlWriter x = XmlWriter.Create(filename)) {
// Create XML document
#region dont-format-this // <-- Any way to get VS to recognize something like this?
x.WriteStartDocument();
x.WriteStartElement("RootElement");
x.WriteStartElement("ChildElement1");
x.WriteStartElement("GrandchildElement1a");
x.WriteElementString("GreatGrandchildElement1a1");
x.WriteElementString("GreatGrandchildElement1a2");
x.WriteEndElement();
x.WriteElementString("GrandchildElement1b");
x.WriteEndElement();
x.WriteStartElement("ChildElement2");
x.WriteEndElement();
x.WriteEndElement();
x.WriteEndDocument();
#endregion
}
}
Run Code Online (Sandbox Code Playgroud)
显然我不希望Visual Studio猜测如何格式化我正在做的事情,但我宁愿它不要在这个区域内尝试.否则每次我编辑一行时,VS都会雄心勃勃并试图撤消我的工作.
c# formatting visual-studio-2010 visual-studio visual-studio-2015
我有以下场景,我认为这可能很常见:
有一个任务(一个UI命令处理程序)可以同步或异步完成.
命令的到达速度可能比处理它们的速度快.
如果命令已有待处理任务,则应对新命令处理程序任务进行排队并按顺序处理.
每个新任务的结果可能取决于前一个任务的结果.
应该遵守取消,但为了简单起见,我想将其排除在本问题的范围之外.此外,线程安全(并发)不是必需的,但必须支持重入.
这是我想要实现的基本示例(作为控制台应用程序,为简单起见):
using System;
using System.Threading.Tasks;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var asyncOp = new AsyncOp<int>();
Func<int, Task<int>> handleAsync = async (arg) =>
{
Console.WriteLine("this task arg: " + arg);
//await Task.Delay(arg); // make it async
return await Task.FromResult(arg); // sync
};
Console.WriteLine("Test #1...");
asyncOp.RunAsync(() => handleAsync(1000));
asyncOp.RunAsync(() => handleAsync(900));
asyncOp.RunAsync(() => handleAsync(800));
asyncOp.CurrentTask.Wait();
Console.WriteLine("\nPress any key to continue to test #2...");
Console.ReadLine();
asyncOp.RunAsync(() =>
{
asyncOp.RunAsync(() => handleAsync(200)); …Run Code Online (Sandbox Code Playgroud) 我想有一个通用的可重用的代码为包装EAP模式的任务,类似什么东西Task.Factory.FromAsync了呢BeginXXX/EndXXXAPM模式.
例如:
private async void Form1_Load(object sender, EventArgs e)
{
await TaskExt.FromEvent<EventArgs>(
handler => this.webBrowser.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(handler),
() => this.webBrowser.Navigate("about:blank"),
handler => this.webBrowser.DocumentCompleted -=
new WebBrowserDocumentCompletedEventHandler(handler),
CancellationToken.None);
this.webBrowser.Document.InvokeScript("setTimeout",
new[] { "document.body.style.backgroundColor = 'yellow'", "1" });
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,它看起来像这样:
public static class TaskExt
{
public static async Task<TEventArgs> FromEvent<TEventArgs>(
Action<EventHandler<TEventArgs>> registerEvent,
Action action,
Action<EventHandler<TEventArgs>> unregisterEvent,
CancellationToken token)
{
var tcs = new TaskCompletionSource<TEventArgs>();
EventHandler<TEventArgs> handler = (sender, args) =>
tcs.TrySetResult(args);
registerEvent(handler);
try
{
using …Run Code Online (Sandbox Code Playgroud) c# ×9
.net ×8
async-await ×7
asynchronous ×3
build ×1
c#-5.0 ×1
com-interop ×1
diff ×1
events ×1
focus ×1
formatting ×1
generics ×1
git ×1
patch ×1
wpf ×1
xaml ×1