Skip to content

Commit 8a1bbce

Browse files
committed
* Implemented new AsyncRunner: a helper which is very useful in controllers to execute background tasks in 'fire and forget' manner. Also spawns a new Autofac lifetime scope for the task thread.
* Refactored StaticCache: it uses own instance instead of static MemoryCache.Default now. Since StaticCache is resolved as a Singleton, it's OK. * Renamed IOC cache names from 'sm_cache_static' to just 'cache' etc.
1 parent 4301d67 commit 8a1bbce

16 files changed

Lines changed: 270 additions & 57 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using Autofac;
5+
using SmartStore.Core.Infrastructure;
6+
using SmartStore.Core.Infrastructure.DependencyManagement;
7+
8+
namespace SmartStore.Core.Async
9+
{
10+
11+
public interface IAsyncRunner
12+
{
13+
Task Run(Action<ILifetimeScope> action, CancellationToken cancellationToken, TaskCreationOptions options, TaskScheduler scheduler);
14+
}
15+
16+
public static class IAsyncRunnerExtensions
17+
{
18+
public static Task Run(this IAsyncRunner runner, Action<ILifetimeScope> action)
19+
{
20+
return runner.Run(action, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
21+
}
22+
23+
public static Task Run(this IAsyncRunner runner, Action<ILifetimeScope> action, CancellationToken cancellationToken)
24+
{
25+
return runner.Run(action, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
26+
}
27+
28+
public static Task Run(this IAsyncRunner runner, Action<ILifetimeScope> action, TaskCreationOptions options)
29+
{
30+
return runner.Run(action, CancellationToken.None, options, TaskScheduler.Default);
31+
}
32+
33+
public static Task Run(this IAsyncRunner runner, Action<ILifetimeScope> action, CancellationToken cancellationToken, TaskCreationOptions options)
34+
{
35+
return runner.Run(action, cancellationToken, options, TaskScheduler.Default);
36+
}
37+
38+
public static Task Run(this IAsyncRunner runner, Action<ILifetimeScope> action, TaskScheduler scheduler)
39+
{
40+
return runner.Run(action, CancellationToken.None, TaskCreationOptions.None, scheduler);
41+
}
42+
}
43+
44+
public class AsyncRunner : IAsyncRunner
45+
{
46+
public Task Run(Action<ILifetimeScope> action, CancellationToken cancellationToken, TaskCreationOptions options, TaskScheduler scheduler)
47+
{
48+
Guard.ArgumentNotNull(() => action);
49+
Guard.ArgumentNotNull(() => scheduler);
50+
51+
var t = Task.Factory.StartNew(() => {
52+
using (var container = EngineContext.Current.ContainerManager.Container.BeginLifetimeScope(AutofacLifetimeScopeProvider.HttpRequestTag))
53+
{
54+
action(container);
55+
}
56+
}, cancellationToken, options, scheduler);
57+
58+
return t;
59+
}
60+
}
61+
62+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
using System;
2+
using System.Collections.Concurrent;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading;
7+
8+
namespace SmartStore.Core.Async
9+
{
10+
11+
public class AsyncState
12+
{
13+
private readonly static AsyncState s_instance = new AsyncState();
14+
private readonly ConcurrentDictionary<StateKey, StateInfo> _states = new ConcurrentDictionary<StateKey, StateInfo>();
15+
16+
private AsyncState()
17+
{
18+
}
19+
20+
public static AsyncState Current
21+
{
22+
get { return s_instance; }
23+
}
24+
25+
public bool Exists<T>(string name = null)
26+
{
27+
var key = BuildKey<T>(name);
28+
return _states.ContainsKey(key) && !object.Equals(_states[key].Progress, default(T));
29+
}
30+
31+
public T Get<T>(string name = null)
32+
{
33+
CancellationTokenSource cancelTokenSource;
34+
return Get<T>(out cancelTokenSource, name);
35+
}
36+
37+
public CancellationTokenSource GetCancelTokenSource<T>(string name = null)
38+
{
39+
CancellationTokenSource cancelTokenSource;
40+
Get<T>(out cancelTokenSource, name);
41+
return cancelTokenSource;
42+
}
43+
44+
private T Get<T>(out CancellationTokenSource cancelTokenSource, string name = null)
45+
{
46+
cancelTokenSource = null;
47+
var key = BuildKey<T>(name);
48+
StateInfo value;
49+
if (_states.TryGetValue(key, out value))
50+
{
51+
cancelTokenSource = value.CancellationTokenSource;
52+
return (T)(value.Progress);
53+
}
54+
55+
return default(T);
56+
}
57+
58+
public void Set<T>(T state, string name = null)
59+
{
60+
this.Set(state, null, name);
61+
}
62+
63+
public void SetCancelTokenSource<T>(CancellationTokenSource cancelTokenSource, string name = null)
64+
{
65+
Guard.ArgumentNotNull(() => cancelTokenSource);
66+
67+
this.Set<T>(default(T), cancelTokenSource, name);
68+
}
69+
70+
private void Set<T>(T state, CancellationTokenSource cancelTokenSource, string name = null)
71+
{
72+
_states.AddOrUpdate(
73+
BuildKey(typeof(T), name),
74+
(key) => new StateInfo { Progress = state, CancellationTokenSource = cancelTokenSource },
75+
(key, old) =>
76+
{
77+
old.Progress = state;
78+
if (cancelTokenSource != null && old.CancellationTokenSource == null)
79+
{
80+
old.CancellationTokenSource = cancelTokenSource;
81+
}
82+
return old;
83+
});
84+
}
85+
86+
public bool Remove<T>(string name = null)
87+
{
88+
var key = BuildKey<T>(name);
89+
StateInfo value;
90+
if (_states.TryRemove(key, out value))
91+
{
92+
if (value.CancellationTokenSource != null)
93+
{
94+
value.CancellationTokenSource.Dispose();
95+
}
96+
return true;
97+
}
98+
99+
return false;
100+
}
101+
102+
private StateKey BuildKey<T>(string name)
103+
{
104+
return BuildKey(typeof(T), name);
105+
}
106+
107+
private StateKey BuildKey(Type type, string name)
108+
{
109+
return new StateKey(type, name);
110+
}
111+
112+
class StateKey : Tuple<Type, string>
113+
{
114+
public StateKey(Type type, string token) : base(type, token)
115+
{
116+
Guard.ArgumentNotNull(() => type);
117+
}
118+
119+
public Type StateType
120+
{
121+
get { return base.Item1; }
122+
}
123+
124+
public string Token
125+
{
126+
get { return base.Item2; }
127+
}
128+
}
129+
130+
class StateInfo
131+
{
132+
public object Progress
133+
{
134+
get;
135+
set;
136+
}
137+
138+
public CancellationTokenSource CancellationTokenSource
139+
{
140+
get;
141+
set;
142+
}
143+
}
144+
}
145+
146+
}

src/Libraries/SmartStore.Core/Caching/StaticCache.cs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,31 @@ namespace SmartStore.Core.Caching
88

99
public partial class StaticCache : ICache
1010
{
11-
private const string REGION_NAME = "$$SmartStoreNET$$";
1211
private readonly static object s_lock = new object();
12+
private ObjectCache _cache;
1313

1414
protected ObjectCache Cache
1515
{
1616
get
1717
{
18-
return MemoryCache.Default;
18+
if (_cache == null)
19+
{
20+
_cache = new MemoryCache("SmartStore");
21+
}
22+
return _cache;
1923
}
2024
}
2125

2226
public IEnumerable<KeyValuePair<string, object>> Entries
2327
{
2428
get
2529
{
26-
return from entry in Cache
27-
where entry.Key.StartsWith(REGION_NAME)
28-
select new KeyValuePair<string, object>(
29-
entry.Key.Substring(REGION_NAME.Length),
30-
entry.Value);
30+
return Cache;
3131
}
3232
}
3333

3434
public T Get<T>(string key, Func<T> acquirer, int? cacheTime)
3535
{
36-
key = BuildKey(key);
37-
3836
if (Cache.Contains(key))
3937
{
4038
return (T)Cache.Get(key);
@@ -68,17 +66,12 @@ public T Get<T>(string key, Func<T> acquirer, int? cacheTime)
6866

6967
public bool Contains(string key)
7068
{
71-
return Cache.Contains(BuildKey(key));
69+
return Cache.Contains(key);
7270
}
7371

7472
public void Remove(string key)
7573
{
76-
Cache.Remove(BuildKey(key));
77-
}
78-
79-
private string BuildKey(string key)
80-
{
81-
return key.HasValue() ? REGION_NAME + key : null;
74+
Cache.Remove(key);
8275
}
8376

8477
}

src/Libraries/SmartStore.Services/Caching/ClearCacheTask.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using SmartStore.Core.Caching;
2+
using SmartStore.Core.Infrastructure;
23
using SmartStore.Services.Tasks;
34

45
namespace SmartStore.Services.Caching
@@ -13,7 +14,7 @@ public partial class ClearCacheTask : ITask
1314
/// </summary>
1415
public void Execute()
1516
{
16-
var cacheManager = new DefaultCacheManager(new StaticCache());
17+
var cacheManager = EngineContext.Current.Resolve<ICacheManager>("static");
1718
cacheManager.Clear();
1819
}
1920
}

0 commit comments

Comments
 (0)