. NET Framework interfaces and classes.
. NET provides many viewmodel interfaces and classes that can be implemented or integrated to view through XAML data binding. Most of these implementations are implemented through Observer pattern. (One of the 23 design modes written by gof)
Observer Pattern
Define a one-to-many dependency between objects. When the State of an object changes, all objects dependent on it will be notified and automatically updated.
In the. net clr language, such as VB or C #, the observer pattern is implemented in the event format in the language design. Based on a publishing and subscription model, an event is triggered by an object and other objects that have subscribed to the event will receive event-triggered notifications. The subscriber list is managed through events and the event can be registered or uninstalled using the +-operator.
The observer pattern can be loosely coupled between the publisher and the subscriber. The publisher does not know its subscriber at all. When the subscriber applies to the publisher, we can say that the dependency is from the subscriber to the publisher.
Without this mode, if you want to notify an object of state changes, you have to continuously check its value for changes caused by State. This process is called poll, and it is the opposite of the observer. For poll changes, you need a continuous loop to know that a change is discovered and to take action on it. This is very inefficient, so an event-based model is easy to gain. UML Model
Inotifypropertychanged Interface
The innoitfypropertychanged interface is used as a special part to implement the observe pattern mode. The attributes of the subscriber and publisher have been changed.
Event propertychangedeventhandler
Onservable collections:
Inotifycollectionchanged is similar to innoitfypropertychanged.
Observablecollection <t>
Readonlyobservablecollection <t>
Collectionviewsource: You can use collcetionviewsource to grouping sorting filtering.
Concurrent processing:
Thread: In an applicationProgramThere are multiple threads in the process. When the process is running, the operating system determines which thread will run and how long it will run. Each thread can process anyCode.
In a single CPU and single-core machine, there is no real concurrency, because the CPU can always execute only one command at a time, and the concurrency on a non-multi-processor machine is an illusion. However, threads are extremely useful in many cases, especially when binding tasks is blocked.
Binding a task is a bottleneck (bottleneck) that needs to be overcome in the Code if there are more resources. Tasks are bound to many different resources, but they do not include:
CPU speed
Input/Output resources: Network, CPU cache,
Example:
IPaddress = IPaddress. parse ("127.0.0.1 ");
Int portnumber = 1500;
Tcplistener Server = new tcplistener (IPaddress, portnumber );
Try
{
Server. Start ();
// This call blocks until a client is wrongly ed
Tcpclient client = server. accepttcpclient ();
Console. writeline ("Client Connected! ");
Client. Close ();
}
Catch (socketexception ex)
{
Console. writeline ("socket exception caught: {0}", ex );
}
Finally
{
Server. Stop ();
}
Console. readkey ();
Accepttcpclient () is a blocking call. The next line of code is not executed until accepttcpclient () returns the result. However, accepttcpclient () depends on the tcp client to connect to the port. The corresponding time may be fast or several hours, but during this blocking time, in addition to waiting for the application to do nothing, multithreading will work. Calling accepttcpclient can run in different threads, and other threads can freely continue to process other useful tasks. A thread is blocked and the main thread can continue. However, the framework provides the ability to call blocking methods asynchronously. Tcplistener exposes the beginaccepttcpclient and endaccepttcpclient methods. Therefore, the above Code can be written as follows:
Tcplistener Server = new tcplistener (IPaddress, portnumber );
Try
{
Server. Start ();
// This call returns immediately, but there is no guarantee when a client
Connects
Server. beginaccepttcpclient (New asynccallback (clientconnected), server );
}
Catch (socketexception ex)
{
Console. writeline ("socket exception caught: {0}", ex );
Server. Stop ();
}
Console. readkey ();
Private Static void clientconnected (iasyncresult asyncresult)
{
Tcplistener Server = asyncresult. asyncstate as tcplistener;
Tcpclient client = server. endaccepttcpclient (asyncresult );
Console. writeline ("Client Connected! ");
Server. Stop ();
}
This is only one of the methods. The server can listen to connections on different threads, so that the application will not be blocked and can process tasks continuously.
Increased complexity
The thread may allow binding tasks to retain functions and responses, but this brings a high price, not only the application is more difficult to understand, but also the multi-threaded application is extremely difficult to adjust, developers have no foreseeable sequence of program execution. The thread means that the program stops at any time and runs different threads before returning the original thread to continue.
Shared Memory
The problem mainly occurs when the memory is shared between two or more threads. If the shared memory is read-only, there will be no too many problems because the resources read by the exaggerated thread can be consistent. However, if one thread writes data to the memory, the data read by other threads will be inconsistent. To overcome this problem, the data in the shared memory is not changeable, but the thread usage is limited. If the shared memory is writable, access to the read/write data will be mediated so that the data remains consistent among multiple threads.
Race Condition
Example:
Object lockobj = new object ();
Ilist <string> List = new list <string> ();
List. Add ("hello ");
...
// Multi-threaded code
Lock (lockobj)
{
If (list. Count> 0)
{
List. removeat (0 );
}
}
Many codes are prone to concurrent errors in multiple threads. The code above runs t1 and t2 in two threads. When T1 checks the Count attribute of list and returns value1. when the operating system stops T1, switch and run t2.t2 to check the Count attribute and get value1. T2 continues to execute the content in the IF statement. Remove the first string in the list. If T1 is also executing the remove operation, this will throw argumentoutofrangeexception
To prevent such competition, code should be locked to ensure that access is restricted, with only one thread at a time.
Object lockobj = new object ();
Ilist <string> List = new list <string> ();
List. Add ("hello ");
...
// Multi-threaded code
Lock (lockobj)
{
If (list. Count> 0)
{
List. removeat (0 );
}
}
Now list is to prevent concurrent access.
Deadlock...
Thread in WPF and Silverlight: in WPF, there are two threads, one for rendering and the other for processing the UI and application code. However, the second thread has multiple responses, if we use a button click event to call system. threading. thread. sleep (10000), the whole UI thread will have no response for 10 seconds at all, because the thread responsible for updating the user interface is the thread currently processing the button event. Normally, this is not a problem. However, if your model and viewmodel accept an event from the thread rather than a UI thread, the invalidoperationexception will occur if they attempt to update the UI.
Dispatcher and dispatcherobjects
Example:
Viewmodel = datacontext as viewmodel;
Dispatcher. Invoke (
(Action) Delegate
{
Viewmodel. Messages. Add (Message );
}
);