You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+58-10Lines changed: 58 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,9 +1,9 @@
1
1
# SerialQueue
2
2
C# Implementation of a SerialQueue in the style of Apple's Grand Central Dispatch queues.
3
3
4
-
Provided as a portable class library targeting .NET 4.5.1 / Windows 8.1 or newer.
4
+
Provided as a Nuget package built for Net462 and NetStandard20
5
5
6
-
##What is a Serial Queue?
6
+
##What is a Serial Queue?
7
7
8
8
[Apple's Grand Central Dispatch library](https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html)
9
9
provides three kinds of "operation queues".
@@ -19,7 +19,7 @@ Serial queues on the other hand have no built-in equivalent. Apple's documentati
19
19
> Serial queues (also known as private dispatch queues) execute one task at a time in the order in which they are added to the queue. The currently executing task runs on a distinct thread (which can vary from task to task) that is managed by the dispatch queue. Serial queues are often used to synchronize access to a specific resource.
20
20
> You can create as many serial queues as you need, and each queue operates concurrently with respect to all other queues. In other words, if you create four serial queues, each queue executes only one task at a time but up to four tasks could still execute concurrently, one from each queue.
21
21
22
-
##Why would I want to use one?
22
+
##Why would I want to use one?
23
23
24
24
There are quite a few scenarios where one might like to use a thread to ensure thread-safety of some object (e.g. "All accesses to the private data of X object must be performed on thread Y"), however threads themselves are often too resource-intensive to be able to do that at a smaller scale (e.g. where you have thousands of such objects.)
25
25
@@ -32,17 +32,65 @@ Serial queues offer a very interesting option in the "middle" of these two space
32
32
33
33
# Example
34
34
35
-
var q = new SerialQueue();
36
-
q.DispatchAsync(() => {
37
-
Console.WriteLine("a");
38
-
});
39
-
q.DispatchAsync(() => {
40
-
Console.WriteLine("b");
41
-
});
35
+
```csharp
36
+
varq=newSerialQueue();
37
+
q.DispatchAsync(() => {
38
+
Console.WriteLine("a");
39
+
});
40
+
q.DispatchAsync(() => {
41
+
Console.WriteLine("b");
42
+
});
43
+
```
42
44
43
45
In the above example, both operations are guaranteed to execute in-order and guaranteed not to execute at the same time.
44
46
Thus, the actions are thread-safe and easy to reason about.
45
47
46
48
The actual execution of the functions is managed by the built-in .NET ThreadPool (the default implementation just uses `Task.Run`) so many thousands of queues will be backed by perhaps 8 or so underlying OS threads in the threadpool
47
49
50
+
## Enhancements for .NET
51
+
52
+
This serial queue supports async/await - i.e. if you are running within the context of a serial queue, then it will be captured across Async/Await
53
+
54
+
```csharp
55
+
varq=newSerialQueue();
56
+
q.DispatchAsync(async () => {
57
+
// we are on the queue
58
+
59
+
varresponse=awaitSomeNetworkRequest();
60
+
61
+
// we are still on the queue, it was captured by the await
62
+
});
63
+
```
64
+
65
+
You can also await the queue itself directly in order to "jump" to it if you are in an existing async method
66
+
67
+
```csharp
68
+
SerialQueuem_queue=newSerialQueue();
69
+
70
+
// imagine this is a WPF or winforms app
71
+
publicvoidButton_Click()
72
+
{
73
+
// here we are on the UI main thread
74
+
varresult=awaitDoBackgroundProcessing();
75
+
76
+
// and we are still on the UI thread because 'await DoBackgroundProcessing' captured the sync context.
77
+
MyTextBox.Text=result;
78
+
}
79
+
80
+
privateasyncTask<string>DoBackgroundProcessing()
81
+
{
82
+
// at this point we are still on the UI main thread
83
+
84
+
awaitm_queue;
85
+
86
+
// now we are OFF the main UI thread and onto the serial queue (behind the scenes we're on a threadpool thread)
87
+
88
+
varresponse=awaitSendNetworkRequest();
89
+
90
+
// still on the serial queue
91
+
92
+
returnresponse;
93
+
}
94
+
```
95
+
48
96
More Documentation is available on the [Github wiki](https://github.com/borland/SerialQueue/wiki)
Copy file name to clipboardExpand all lines: src/Interfaces.cs
+28Lines changed: 28 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -18,6 +18,7 @@
18
18
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
// THE SOFTWARE.
20
20
usingSystem;
21
+
usingSystem.Runtime.CompilerServices;
21
22
usingSystem.Threading.Tasks;
22
23
23
24
#nullable enable
@@ -50,6 +51,9 @@ public interface IDispatchQueue : IDisposable
50
51
/// <summary>Checks whether the currently-executing function is
51
52
/// on this queue, and throw an OperationInvalidException if it is not</summary>
52
53
voidVerifyQueue();
54
+
55
+
/// <summary>Returns the display-name of the queue (if one is set) for diagnostic purposes</summary>
56
+
string?Name{get;}
53
57
}
54
58
55
59
/// <summary>A serial queue needs a threadpool to run tasks on. You can provide your own implementation if you want to have a custom threadpool with it's own limits (e.g. no more than X concurrent threads)</summary>
0 commit comments