我有以下四个测试,当我运行它时,最后一个测试挂起,我的问题是为什么会发生这种情况:
[Test]
public void CheckOnceResultTest()
{
Assert.IsTrue(CheckStatus().Result);
}
[Test]
public async void CheckOnceAwaitTest()
{
Assert.IsTrue(await CheckStatus());
}
[Test]
public async void CheckStatusTwiceAwaitTest()
{
Assert.IsTrue(await CheckStatus());
Assert.IsTrue(await CheckStatus());
}
[Test]
public async void CheckStatusTwiceResultTest()
{
Assert.IsTrue(CheckStatus().Result); // This hangs
Assert.IsTrue(await CheckStatus());
}
private async Task<bool> CheckStatus()
{
var restClient = new RestClient(@"https://api.test.nordnet.se/next/1");
Task<IRestResponse<DummyServiceStatus>> restResponse = restClient.ExecuteTaskAsync<DummyServiceStatus>(new RestRequest(Method.GET));
IRestResponse<DummyServiceStatus> response = await restResponse;
return response.Data.SystemRunning;
}
Run Code Online (Sandbox Code Playgroud)
我将此扩展方法用于restsharp RestClient:
public static class RestClientExt
{
public static Task<IRestResponse<T>> ExecuteTaskAsync<T>(this RestClient client, IRestRequest …Run Code Online (Sandbox Code Playgroud) 有人可以解释,如果await和ContinueWith是在下面的例子中同义与否.我正在尝试第一次使用TPL并且已经阅读了所有文档,但是不明白其中的区别.
等待:
String webText = await getWebPage(uri);
await parseData(webText);
Run Code Online (Sandbox Code Playgroud)
继续:
Task<String> webText = new Task<String>(() => getWebPage(uri));
Task continue = webText.ContinueWith((task) => parseData(task.Result));
webText.Start();
continue.Wait();
Run Code Online (Sandbox Code Playgroud)
在特定情况下,一个优先于另一个吗?
我正在阅读Stephen Cleary撰写的"C#Cookbook中的并发",我注意到以下技巧:
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if (completedTask == timeoutTask)
return null;
return await downloadTask;
Run Code Online (Sandbox Code Playgroud)
downloadTask是对httpclient.GetStringAsync的调用,timeoutTask正在执行Task.Delay.
如果它没有超时,则downloadTask已经完成.为什么有必要做第二次等待而不是返回downloadTask.Result,因为任务已经完成了?
我在这里发现了类似的问题,但没有我满意的答案.所以再次重述这个问题 -
我有一项需要定期完成的任务(比如每隔1分钟).使用Timertask&Timer执行此操作的优势是什么,而不是创建一个具有无限循环睡眠的新线程?
使用timertask-的代码段 -
TimerTask uploadCheckerTimerTask = new TimerTask(){
public void run() {
NewUploadServer.getInstance().checkAndUploadFiles();
}
};
Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);
Run Code Online (Sandbox Code Playgroud)
使用Thread和sleep的代码片段 -
Thread t = new Thread(){
public void run() {
while(true) {
NewUploadServer.getInstance().checkAndUploadFiles();
Thread.sleep(60 * 1000);
}
}
};
t.start();
Run Code Online (Sandbox Code Playgroud)
如果逻辑执行时间超过间隔时间,我真的不必担心是否会错过某些周期.
请评论这个..
更新:
最近我发现使用Timer与Thread.sleep()之间存在另一个区别.假设当前系统时间是上午11:00.如果由于某种原因我们将系统时间回滚到上午10:00,则计时器将停止执行任务,直到它到达上午11:00,而Thread.sleep()方法将继续执行任务而不受阻碍.这可能是决定在这两者之间使用什么的主要决策者.
OperationCanceledException和之间有什么区别TaskCanceledException?如果我使用.NET 4.5并使用async/ awaitkeywords,我应该抓住哪一个?
这意味着什么以及如何解决它?
我正在使用TPL任务.
整个错误
通过等待任务或访问其Exception属性,未观察到任务的异常.结果,终结器线程重新抛出了未观察到的异常.
在System.Threading.Tasks.TaskExceptionHolder.Finalize()
mscorlib程序
我有一些库(套接字网络)代码,它Task基于提供基于API的待处理请求响应TaskCompletionSource<T>.然而,TPL中的一个烦恼是,似乎不可能阻止同步延续.我会希望能够做的是两种:
TaskCompletionSource<T>不应该允许呼叫者附加TaskContinuationOptions.ExecuteSynchronously,或SetResult/ TrySetResult)以指定TaskContinuationOptions.ExecuteSynchronously应该忽略的方式具体来说,我遇到的问题是传入的数据正在由专用的阅读器处理,如果调用者可以附加,TaskContinuationOptions.ExecuteSynchronously他们可以阻止阅读器(这不仅影响它们).以前,我通过一些hackery解决了这个问题,它检测是否存在任何延续,如果它们将完成推送到ThreadPool,那么如果调用者已经使工作队列饱和,则会产生重大影响,因为完成将不会被处理及时.如果他们使用Task.Wait()(或类似),他们将基本上陷入僵局.同样,这就是读者使用专用线程而不是使用工作者的原因.
所以; 在我尝试唠叨TPL团队之前:我错过了一个选项吗?
关键点:
ThreadPool作为一个实现,因为它需要在池饱和时工作以下示例生成输出(排序可能因时间而异):
Continuation on: Main thread
Press [return]
Continuation on: Thread pool
Run Code Online (Sandbox Code Playgroud)
问题在于随机调用者设法在"主线程"上获得延续.在实际代码中,这将打断主要读者; 坏事!
码:
using System;
using System.Threading;
using System.Threading.Tasks;
static class Program
{
static void Identify()
{
var thread = Thread.CurrentThread;
string name = thread.IsThreadPoolThread
? "Thread pool" : thread.Name;
if (string.IsNullOrEmpty(name))
name = …Run Code Online (Sandbox Code Playgroud) 我有一个rake任务,在我的rails应用程序中填充一些初始数据.例如,国家,州,移动运营商等
我现在设置它的方式是,我在/ db/fixtures中的文件中有一堆create语句,还有一个处理它们的rake任务.例如,我有一个模型是主题.我在/ db/fixtures中有一个theme.rb文件,如下所示:
Theme.delete_all
Theme.create(:id => 1, :name=>'Lite', :background_color=>'0xC7FFD5', :title_text_color=>'0x222222',
:component_theme_color=>'0x001277', :carrier_select_color=>'0x7683FF', :label_text_color=>'0x000000',
:join_upper_gradient=>'0x6FAEFF', :join_lower_gradient=>'0x000000', :join_text_color=>'0xFFFFFF',
:cancel_link_color=>'0x001277', :border_color=>'0x888888', :carrier_text_color=>'0x000000', :public => true)
Theme.create(:id => 2, :name=>'Metallic', :background_color=>'0x000000', :title_text_color=>'0x7299FF',
:component_theme_color=>'0xDBF2FF', :carrier_select_color=>'0x000000', :label_text_color=>'0xDBF2FF',
:join_upper_gradient=>'0x2B25FF', :join_lower_gradient=>'0xBEFFAC', :join_text_color=>'0x000000',
:cancel_link_color=>'0xFF7C12', :border_color=>'0x000000', :carrier_text_color=>'0x000000', :public => true)
Theme.create(:id => 3, :name=>'Blues', :background_color=>'0x0060EC', :title_text_color=>'0x000374',
:component_theme_color=>'0x000374', :carrier_select_color=>'0x4357FF', :label_text_color=>'0x000000',
:join_upper_gradient=>'0x4357FF', :join_lower_gradient=>'0xffffff', :join_text_color=>'0x000000',
:cancel_link_color=>'0xffffff', :border_color=>'0x666666', :carrier_text_color=>'0x000000', :public => true)
puts "Success: Theme data loaded"
Run Code Online (Sandbox Code Playgroud)
这里的想法是我想为用户安装一些股票主题.我有这个方法的问题.
设置ID不起作用.这意味着如果我决定添加一个主题,让我们称之为"红色",那么我只想将主题语句添加到此fixture文件并调用rake任务来重新设置数据库.如果我这样做,因为主题属于其他对象,并且在重新初始化时它们的id发生了变化,所有链接都会被破坏.
我的问题首先是,这是处理数据库播种的好方法吗?在上一篇文章中,我向你推荐了这个.
如果是这样,我怎么能对ID进行硬编码,这有什么缺点吗?
如果没有,那么种子数据库的最佳方法是什么?
我将真正感谢包含最佳实践的长期和深思熟虑的答案.
我一直在研究这个问题,但至少我还是非常困惑.
谁能给我一个何时使用Task和何时使用的具体例子Platform.runLater(Runnable);?究竟有什么区别?什么时候使用其中任何一个是否有黄金法则?
如果我错了也不纠正我,但这两个"对象"不是在GUI中用于更新GUI的主线程内创建另一个线程的方法吗?
我从一个函数开始一个新的任务,但我不希望它在同一个线程上运行.我不关心它运行在哪个线程上,只要它是一个不同的线程(因此这个问题中给出的信息没有帮助).
我保证TestLock在允许Task t再次输入之前,以下代码将始终退出吗?如果没有,建议的设计模式是什么来防止再次出现?
object TestLock = new object();
public void Test(bool stop = false) {
Task t;
lock (this.TestLock) {
if (stop) return;
t = Task.Factory.StartNew(() => { this.Test(stop: true); });
}
t.Wait();
}
Run Code Online (Sandbox Code Playgroud)
编辑:基于Jon Skeet和Stephen Toub的以下答案,确定性地防止重入的一种简单方法是传递CancellationToken,如此扩展方法所示:
public static Task StartNewOnDifferentThread(this TaskFactory taskFactory, Action action)
{
return taskFactory.StartNew(action: action, cancellationToken: new CancellationToken());
}
Run Code Online (Sandbox Code Playgroud)