Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.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
C# 如何使用任务有条件地异步运行代码_C#_.net_Multithreading_.net 4.0_Task Parallel Library - Fatal编程技术网

C# 如何使用任务有条件地异步运行代码

C# 如何使用任务有条件地异步运行代码,c#,.net,multithreading,.net-4.0,task-parallel-library,C#,.net,Multithreading,.net 4.0,Task Parallel Library,我有一个类负责检索资源,该类还缓存资源以便快速访问。 该类公开了用于检索资源的异步方法: public Task<object> GetResourceAsync(string resourceName) { return Task.Factory.StartNew<object>(() => { // look in cache // if not found, get from disk //

我有一个类负责检索资源,该类还缓存资源以便快速访问。 该类公开了用于检索资源的异步方法:

public Task<object> GetResourceAsync(string resourceName)
{
    return Task.Factory.StartNew<object>(() =>
    {
        // look in cache

        // if not found, get from disk

        // return resource
    });
}
公共任务GetResourceAsync(字符串resourceName) { 返回Task.Factory.StartNew(()=> { //在缓存中查找 //如果未找到,请从磁盘获取 //返回资源 }); } 客户端代码如下所示:

myResourceProvider.GetResourceAsync("myResource")
    .ContinueWith<object>(t => Console.WriteLine("Got resource " + t.Result.ToString()));
myResourceProvider.GetResourceAsync(“myResource”)
.ContinueWith(t=>Console.WriteLine(“获取资源”+t.Result.ToString());
这样,始终使用背景线程。但是,如果在缓存中找到对象,我不希望代码异步运行。 如果它是在缓存中找到的,我希望立即返回资源,而不必使用其他线程

谢谢。

.NET 4.5有一个函数,允许您返回
任务
,但它没有在线程池线程上运行委托,而是显式设置任务的返回值

因此,在代码的上下文中:

public Task<object> AsyncGetResource(string resourceName)
{
    object valueFromCache;
    if (_myCache.TryGetValue(resourceName, out valueFromCache)) {
        return Task.FromResult(valueFromCache);
    }
    return Task.Factory.StartNew<object>(() =>
    {
        // get from disk
        // add to cache
        // return resource
    });
}
公共任务AsyncGetResource(字符串resourceName)
{
对象值来自缓存;
if(_myCache.TryGetValue(resourceName,out valueFromCache)){
返回Task.FromResult(valueFromCache);
}
返回Task.Factory.StartNew(()=>
{
//从磁盘获取
//添加到缓存
//返回资源
});
}
如果您仍然使用.NET 4.0,则可以使用来执行相同的操作:

var tcs = new TaskCompletionSource<object>();
tcs.SetResult(...item from cache...);
return tcs.Task;
var tcs=new TaskCompletionSource();
SetResult(…缓存中的项…);
返回tcs.Task;

如果有UI连接线程,请小心

在WPF中,使用Task.Run在UI线程(例如按钮单击事件处理程序)上运行非常重要,以避免UI问题,并在后台线程上运行代码

为什么??默认情况下,使用TaskScheduler.default参数(而不是TaskScheduler.Current)在Task.Factory.StartNew周围运行一个包装器

因此,仅仅像这样调用异步方法是不够的,因为它在UI线程上运行并将其冻结:
wait sometaskaync()

您应该在任务内部调用它,而不是它。运行:

  • Task.Run(async()=>wait sometaskaync())
或者在任务中使用syncron方法。运行:

  • Task.Run(()=>SomeTask())

这正是我想要的。谢谢+1我刚才问了这个问题(),现在我知道什么时候应该使用它。@joe你能为Task.FromResult增强这个代码(附加一个解决方案)吗?调用
Task.Factory.StartNew默认使用
TaskScheduler.Current
,在某些情况下,当StartNew启动的任务在UI线程上运行时,这可能会导致意外行为。您应该始终传入
TaskScheduler.Default
或使用
Task.Run
,如果希望代码始终在后台线程上运行,则可以使用它。