|Perhaps the difference comes from the different conditions you are using. In the original, you are not taking "distinct" items only and you are comparing based on both processId and process. In the LINQ version, you are taking both distinct and comparing only on processID.
There is an overload of Except that may help you out here. It takes an additional IEqualityComparer parameter. You can use that parameter to implement the custom equality operation. Also, Except has an implementation detail that trips up everyone the first time they use except. As well as being "Equals", the objects must have the same "GetHashCode" because Except will use a HashSet to store the objects from the first sequence. This also has the side effect of automatically doing a "distinct" on the two sequences. One trick you can use to get around this is to override GetHashCode on your object to just return a constant value that is the same for all instances. The tradeoff is that hashtables and hashsets will go from O(1) to O(n).
Below is a simple IEqualityComparer I whipped up to take a delegate for the comparisons so you don't have to make a separate class for each comparison. (If there is something similar in the framework, I don't know about it.)
Public Class DelegateEqualityComparer(Of T)
Implements IEqualityComparer(Of T)
Public Sub New(ByVal comparison As Func(Of T, T, Boolean))
Public Sub New(ByVal comparison As Func(Of T, T, Boolean), ByVal hash As Func(Of T, Integer))
If comparison Is Nothing Then Throw New ArgumentNullException("comparison")
_comparison = comparison
_hash = hash
Private _comparison As Func(Of T, T, Boolean)
Private _hash As Func(Of T, Integer)
Public Function ComparerEquals(ByVal x As T, ByVal y As T) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of T).Equals
Return _comparison(x, y)
Public Function ComparerGetHashCode(ByVal obj As T) As Integer Implements System.Collections.Generic.IEqualityComparer(Of T).GetHashCode
If _hash Is Nothing Then