-
Oct 18th, 2010, 08:09 AM
#1
Thread Starter
Fanatic Member
How to use Paralell.ForEach with a SearchResultCollection
I can't seem to get the syntax right for a simple Parallel.Foreach Loop.
This is how I would normally iterate a SearchResultCollection
Code:
Dim src As SearchResultCollection = DSearch.FindAll
For Each x As SearchResult In src
Debug.WriteLine(GetProperty(x, "Name"))
'Parallel.ForEach(x, Function(x) Debug.WriteLine(x))
Next
As I have (obviously) misunderstood it this should be the syntax for the Parallel.Foreach
Code:
Parallel.ForEach(src, (Sub(x As SearchResult) GetProperty(x, "Name")))
Parallel.ForEach(src, Function(x) Debug.WriteLine(x))
It's not that though. What's the correct syntax here?
ManagePC - the all-in-one PC management and inventory tool
-
Oct 18th, 2010, 10:02 AM
#2
Re: How to use Paralell.ForEach with a SearchResultCollection
well.... according to the documentation - http://msdn.microsoft.com/en-us/libr...0(VS.100).aspx
... this looks closest correct:
Code:
Parallel.ForEach(src, (Sub(x As SearchResult) GetProperty(x, "Name")))
The only thing that looks off to me is a few extra parenthesis...and a missing end sub
Code:
Parallel.ForEach(src, Sub(x As SearchResult)
GetProperty(x, "Name")
End Sub)
-tg
ADDENDUM - I noticed the example on MSDN didn't type the sub parameter... if that above doesn't work.. try this:
Code:
Parallel.ForEach(src, Sub(x)
GetProperty(x, "Name")
End Sub)
-
Oct 18th, 2010, 10:13 AM
#3
Thread Starter
Fanatic Member
Re: How to use Paralell.ForEach with a SearchResultCollection
Yeah, that's what I've been trying but I get
Error 1 Overload resolution failed because no accessible 'ForEach' can be called with these arguments:
'Public Shared Function ForEach(Of TSource)(source As System.Collections.Concurrent.OrderablePartitioner(Of TSource), body As System.Action(Of TSource, System.Threading.Tasks.ParallelLoopState, Long)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
'Public Shared Function ForEach(Of TSource)(source As System.Collections.Concurrent.Partitioner(Of TSource), body As System.Action(Of TSource, System.Threading.Tasks.ParallelLoopState)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
'Public Shared Function ForEach(Of TSource)(source As System.Collections.Concurrent.Partitioner(Of TSource), body As System.Action(Of TSource)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
'Public Shared Function ForEach(Of TSource)(source As System.Collections.Generic.IEnumerable(Of TSource), body As System.Action(Of TSource, System.Threading.Tasks.ParallelLoopState, Long)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
'Public Shared Function ForEach(Of TSource)(source As System.Collections.Generic.IEnumerable(Of TSource), body As System.Action(Of TSource, System.Threading.Tasks.ParallelLoopState)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
'Public Shared Function ForEach(Of TSource)(source As System.Collections.Generic.IEnumerable(Of TSource), body As System.Action(Of TSource)) As System.Threading.Tasks.ParallelLoopResult': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
ManagePC - the all-in-one PC management and inventory tool
-
Oct 18th, 2010, 11:47 AM
#4
Re: How to use Paralell.ForEach with a SearchResultCollection
What is "DSearch" ? I mean... what object type is it?
-tg
-
Oct 18th, 2010, 12:18 PM
#5
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by techgnome
What is "DSearch" ? I mean... what object type is it?
-tg
System.DirectoryServices.DirectorySearcher at a guess
-
Oct 18th, 2010, 12:30 PM
#6
Re: How to use Paralell.ForEach with a SearchResultCollection
ah hah... I see ... it looks like the SearchResultCollection object returns more than one interface... the foreach can't figure out which one to follow (this is my guess...) ... Try using this:
Code:
Parallel.ForEach(src.GetEnumerator,
If that still doesn't work, then odds are you've got something that isn't going to be compatible with the Parallel.ForEach. In which case, a good old fashioned For Each will have to suffice...
-
Oct 18th, 2010, 12:47 PM
#7
Re: How to use Paralell.ForEach with a SearchResultCollection
I just had a quick look at this and I don't think its possible just using the result from the FindAll method directly because annoyingly you can't cast it to IEnumerable(Of SearchResult) or even ICollection(Of SearchResult) as you would have expected...
The only way I can think of to get it to work is to just add each one of the results to a generic List and then pass the list in to the Parallel.ForEach like so:
vb Code:
Dim RawResults As SearchResultCollection = Searcher.FindAll
Dim ResultsList As New List(Of SearchResult)
For Each Result As SearchResult In RawResults
ResultsList.Add(Result)
Next
Parallel.ForEach(Of SearchResult)(ResultsList, AddressOf GetProperty)
Then the GetProperty method signature is like this:
vb Code:
Private Sub GetProperty(ByVal Result As SearchResult, ByVal state As ParallelLoopState)
'Do whatever you want with the individual SearchResult objects here
End Sub
Not ideal but hopefully it helps
EDIT: Already tried what you suggested TG but unfortunately that doesn't work either. The SearchResultCollection class is a rather annoying class to work with as I have discovered many times in the past...
-
Oct 18th, 2010, 12:50 PM
#8
Re: How to use Paralell.ForEach with a SearchResultCollection
Chris - I thought about that too... looping and putting it into a List... but the point of the Parallel.ForEach is that it does the looping for you. If you're going to loop through it anyways, might as well add the call to the sub in there too. Otherwise, I'm not sure you gain anything. (I could be wrong.)
-tg
-
Oct 18th, 2010, 01:06 PM
#9
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by techgnome
Chris - I thought about that too... looping and putting it into a List... but the point of the Parallel.ForEach is that it does the looping for you. If you're going to loop through it anyways, might as well add the call to the sub in there too. Otherwise, I'm not sure you gain anything. (I could be wrong.)
-tg
I think you definitely still gain something - the point of a loop isn't just to iterate through items in a collection is it, the point is to iterate through the collection and do something with each item in the collection. So in a parallel loop you gain the benefit of that action that you are doing to each item in the collection being performed simultaneously on its own thread without you having to create/manage the threads at all. So unless you were only doing something very trivial and fast with each item then you are bound to notice some performance benefits.
Last edited by chris128; Oct 18th, 2010 at 03:58 PM.
-
Oct 18th, 2010, 01:08 PM
#10
Re: How to use Paralell.ForEach with a SearchResultCollection
Oh and also if you want to make it look a little nicer (and also avoid repeating code if you need to do this in more than one place) then you can use an Extension method like this to add a "ToList" method onto the SearchResultCollection class:
vb Code:
Imports System.DirectoryServices
Module Extensions
<Runtime.CompilerServices.Extension()> _
Public Function ToList(ByVal Instance As SearchResultCollection) As List(Of SearchResult)
Dim FinalList As New List(Of SearchResult)
For Each Result As SearchResult In Instance
FinalList.Add(Result)
Next
Return FinalList
End Function
End Module
Then the previous example can be written like this:
vb Code:
Dim RawResults As SearchResultCollection = Searcher.FindAll
Parallel.ForEach(Of SearchResult)(RawResults.ToList, AddressOf GetProperty)
-
Oct 19th, 2010, 02:17 AM
#11
Thread Starter
Fanatic Member
Re: How to use Paralell.ForEach with a SearchResultCollection
Yup. That worked. Unfortunately, it didn't provide a performance improvement over a normal ForEach.
Oh well. Worth a try
ManagePC - the all-in-one PC management and inventory tool
-
Oct 19th, 2010, 02:52 AM
#12
Re: How to use Paralell.ForEach with a SearchResultCollection
Yeah well like I said it depends what you were actually doing with each item in your GetProperty method
-
Oct 19th, 2010, 03:27 AM
#13
Thread Starter
Fanatic Member
Re: How to use Paralell.ForEach with a SearchResultCollection
Oh, nothing special. It just returned a value from a searchresult property. I was merely intrigued in testing the performance improvements of the new parallel features of .NET 4.0
ManagePC - the all-in-one PC management and inventory tool
-
Oct 19th, 2010, 07:03 AM
#14
Re: How to use Paralell.ForEach with a SearchResultCollection
What is your system specs? Processors, Cores, OS? Each of those will impact the performance as well.
-tg
-
Mar 17th, 2014, 11:46 AM
#15
New Member
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by chris128
vb Code:
Dim RawResults As SearchResultCollection = Searcher.FindAll
Dim ResultsList As New List(Of SearchResult)
For Each Result As SearchResult In RawResults
ResultsList.Add(Result)
Next
Parallel.ForEach(Of SearchResult)(ResultsList, AddressOf GetProperty)
Why are you creating a SearchResultCollection only to convert it to a collection of SearchResult? Seems a bit redundant and over worked. If you're going to loop through everything then you might as well just make it a basic object list since the default for Parallel is object based.
In this example I'll be going through a domain to find all machines:
Code:
Dim dsDomain As System.DirectoryServices.DirectoryEntry = New System.DirectoryServices.DirectoryEntry("LDAP://DC=domain,DC=com")
Dim dsSearcher As System.DirectoryServices.DirectorySearcher = New System.DirectoryServices.DirectorySearcher(dsDomain)
dsSearcher.Filter = ("(objectClass=computer)")
Dim results As New List(Of Object)
For Each machine In dsSearcher.FindAll()
results.Add(Mid(machine.GetDirectoryEntry().Name.ToString(), 4))
Next
Parallel.ForEach(results, _
Sub(machine)
End Sub)
No second method needed and no more conversions.
-
Mar 17th, 2014, 12:10 PM
#16
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by JEmlay
Why are you creating a SearchResultCollection only to convert it to a collection of SearchResult?
Because you have no choice in creating a SearchResultCollection - that is what the FindAll method returns. You can't do a Parallel For Each through that though, which is exactly why the OP posted this question. So my "solution" is to add each result from the SearchResultCollection to a generic List(Of T), which you then can do a Parallel For Each through.
If you're going to loop through everything then you might as well just make it a basic object list since the default for Parallel is object based.
How is that any better? It doesn't cost anything more to create a List(Of SearchResult) than it does to create a List(Of Object) and at least with the List(Of SearchResult) it is strongly typed. I don't understand the argument for using Object instead of a specific class when you know that class is the only type of object you will be adding to that list. As far as I can see there is absolutely no benefit to using Object, whereas there are benefits to actually specifying a type. By your logic, we should just use Object for everything right? Why bother with types at all...
No second method needed and no more conversions.
The second method wasn't "needed" at all (assuming you're referring to the extension method I mentioned) and I didn't even include it in the original post that you quoted. Like I said, that is just to make it look nicer and be slightly more convenient to use. Also I'm not sure what conversions you're referring to. Nowhere in my code am I converting anything - if you're referring to adding each item from the SearchResultCollection to a List(Of SearchResult), you're doing the exact same thing in your code but "converting" to a List(Of Object) which as explained above is worse if anything.
-
Mar 17th, 2014, 12:35 PM
#17
New Member
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by chris128
Because you have no choice in creating a SearchResultCollection - that is what the FindAll method returns. You can't do a Parallel For Each through that though, which is exactly why the OP posted this question.
You didn't understand what I asked.
Originally Posted by chris128
How is that any better? It doesn't cost anything more to create a List(Of SearchResult) than it does to create a List(Of Object)
Yes it does. It cost you your addition sub. You're passing it along yet again. That's completely not needed.
"Private Sub GetProperty'
Not to mention an overly complex call because of it:
Parallel.ForEach(Of SearchResult)(ResultsList, AddressOf GetProperty)
versus
Parallel.ForEach(results, Sub(machine)
If you're going to convert SearchResultCollection FOR PARALLEL then you might as well convert it to the default input for Parallell....now I'm just repeating myself.
-
Mar 17th, 2014, 12:48 PM
#18
Re: How to use Paralell.ForEach with a SearchResultCollection
That's not actually any different at all... you're just writing the method in line rather than as a separate method. Its still the exact same thing that is happening.
Why does converting it so that it fits the default overload of the Parallel For Each make it any better? The default overload is not any "better" than another overload, its just different and used for different circumstances.
In your example you're going to have to convert/cast that Object back to a strongly typed class in your in line Sub anyway (unless you've got Option Strict turned off and are allowing late binding, which a million people on here will tell you is not a good idea), so you're not gaining anything at all. All you are doing is moving the point that you do the casting.
Your example:
Loop through SearchResultCollection and add each SearchResult to a list as an Object.
Pass in items to the in line method as an Object.
Method has to cast them to a SearchResult to be able to use them.
My example:
Loop through SearchResultCollection and add each SearchResult to a list as a SearchResult.
Pass in items to a separate method as a SearchResult.
Method can use them directly.
Can't you see that you're not gaining anything at all?
-
Mar 17th, 2014, 01:02 PM
#19
New Member
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by chris128
That's not actually any different at all... you're just writing the method in line rather than as a separate method. Its still the exact same thing that is happening.
You seem to be turning a blind eye to the fact that you are creating additional work.
"Yes it does. It cost you your addition sub. You're passing it along YET AGAIN. That's completely not needed."
Originally Posted by chris128
Why does converting it so that it fits the default overload of the Parallel For Each make it any better?
Less work.
Originally Posted by chris128
In your example you're going to have to convert/cast that Object back to a strongly typed class in your in line Sub anyway
No, I'm not. How do you figure? The work performed in the ForEach is the end result. Even if you did need to go back BOTH OF THEM EXIST if you need them to.
Originally Posted by chris128
Method has to cast them to a SearchResult to be able to use them.
No, it doesn't.
Simplified code is simplified code. If you want to throw in unneeded extra routines then knock yourself out. I simply provided a more logical and slimmed down way about it for others who find themselves here as I did. I really don't care if you don't like it. It's for others to use.
-
Mar 17th, 2014, 01:18 PM
#20
Re: How to use Paralell.ForEach with a SearchResultCollection
lol so you base the code you use on how easy it is to write rather than how well it performs or how reliable it is? I agree you shouldn't make things overly complex if it can be avoided but in this case I don't think anything here is overly complex and I think it is the best option to use for those of us with Option Strict on (which is almost everyone... but from your code example I can see you don't have it on, which is probably why you are oblivious to the type casting I'm referring to). I still don't see how you think writing Sub/End Sub in line is any less work than writing it as a separate method - you still type the same characters, just in a different place.
Yes it does. It cost you your addition sub. You're passing it along YET AGAIN. That's completely not needed
Like I already explained, that additional sub is getting generated either way. You're passing the object on to an additional sub either way - all you're doing is writing that sub in line rather than separately. The EXACT same thing is still happening either way though. Don't believe me? Here's my example method and the resulting code in Reflector after it has been compiled:
vb.net Code:
Imports System.DirectoryServices Imports System.Threading.Tasks Public Class Mine Private Sub Example() Dim Searcher As New DirectorySearcher Dim RawResults As SearchResultCollection = Searcher.FindAll Dim ResultsList As New List(Of SearchResult) For Each Result As SearchResult In RawResults ResultsList.Add(Result) Next Parallel.ForEach(Of SearchResult)(ResultsList, AddressOf GetProperty) End Sub Private Sub GetProperty(ByVal Result As SearchResult, ByVal state As ParallelLoopState) IO.File.WriteAllText("C:\example.txt", Result.Path) End Sub End Class
and here's an example of yours:
vb.net Code:
Imports System.DirectoryServices Imports System.Threading.Tasks Public Class Yours Private Sub Example() Dim Searcher As New DirectorySearcher Dim RawResults As SearchResultCollection = Searcher.FindAll Dim ResultsList As New List(Of Object) For Each Result As SearchResult In RawResults ResultsList.Add(Result) Next Parallel.ForEach(ResultsList, Sub(Machine) IO.File.WriteAllText("C:\example.txt", DirectCast(Machine, SearchResult).Path) End Sub) End Sub End Class
See how a separate sub is still being created in your example even though it was written "in line" in the actual source code? The only difference is the compiler created your extra sub and named it Lamda$_1. Also see how I have to cast the object to a SearchResult to be able to use it? If I don't do that then it won't even compile with Option Strict turned on. Turn it on (as you should anyway) and you'll see what I mean.
Last edited by chris128; Mar 17th, 2014 at 01:22 PM.
-
Mar 17th, 2014, 01:29 PM
#21
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by JEmlay
I simply provided a more logical and slimmed down way about it for others who find themselves here as I did. I really don't care if you don't like it. It's for others to use.
That's fair enough but you didn't just provide a slimmed down version - you specifically asked why I did it the way I did:
"Why are you creating a SearchResultCollection only to convert it to a collection of SearchResult?"
Which is why I answered explaining why I did it that way and not your way. Your example won't even compile for anyone with Option Strict turned on, but yes if you have it turned off and don't care about doing things the best way, just want the simplest method possible with the least amount of typing then your method is fine.
-
Mar 17th, 2014, 01:52 PM
#22
New Member
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by chris128
That's fair enough but you didn't just provide a slimmed down version - you specifically asked why I did it the way I did:
http://tinyurl.com/d36gu3q
Originally Posted by chris128
Your example won't even compile for anyone with Option Strict turned on, but yes if you have it turned off and don't care about doing things the best way, just want the simplest method possible with the least amount of typing then your method is fine.
That's BS and I wont even get into a debate over that. Countless examples of Microsoft's own code wont even compile with it turned on which is why people kill themselves over such ridiculous debates.
-
Mar 17th, 2014, 02:07 PM
#23
Re: How to use Paralell.ForEach with a SearchResultCollection
I've had option strict turned on for the last 3 years at least and never had an issue, and I know most people on these forums have it turned on as well. There have been many threads about it. It simply encourages better programming and in some cases also improved performance and helps avoid potential bugs.
-
Mar 17th, 2014, 02:27 PM
#24
Re: How to use Paralell.ForEach with a SearchResultCollection
This...might seem a little silly due to the original OP's post but...
Code:
Dim src As SearchResultCollection = DSearch.FindAll
For Each x As SearchResult In src
Debug.WriteLine(GetProperty(x, "Name"))
'Parallel.ForEach(x, Function(x) Debug.WriteLine(x))
Next
Couldn't you just...do this?
Code:
Dim src As IEnumerable(Of SearchResult) = DSearch.FindAll().Cast(Of SearchResult)
-
Mar 17th, 2014, 03:12 PM
#25
Re: How to use Paralell.ForEach with a SearchResultCollection
considering the thread was 3 1/2 years old, it seems even more silly.
-tg
-
Mar 17th, 2014, 04:01 PM
#26
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by techgnome
considering the thread was 3 1/2 years old, it seems even more silly.
-tg
I think it's more sad I didn't realize the thread was that old.
-
Mar 17th, 2014, 04:18 PM
#27
New Member
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by formlesstree4
Couldn't you just...do this?
Code:
Dim src As IEnumerable(Of SearchResult) = DSearch.FindAll().Cast(Of SearchResult)
Nope, can't cast a system COM object to IDirectorySearch. IEnumerable is pretty much out the window.
-
Mar 17th, 2014, 05:57 PM
#28
Re: How to use Paralell.ForEach with a SearchResultCollection
Originally Posted by JEmlay
Nope, can't cast a system COM object to IDirectorySearch. IEnumerable is pretty much out the window.
According to the class declaration of FindAll, it returns a SearchResultCollection which is decorated as followed:
Code:
public class SearchResultCollection : MarshalByRefObject, ICollection, IEnumerable, IDisposable
So, since it implements IEnumerable, in theory, we should be able to enumerate through the collection since the value is a SearchResult class. Inside SearchResultCollection, we do see the indexer declared as such:
Code:
public SearchResult this[int index] { get; }
So far so good.
Now, Cast is declared in Enumerable.cs as such:
Code:
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) {
IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
if (typedSource != null) return typedSource;
if (source == null) throw Error.ArgumentNull("source");
return CastIterator<TResult>(source);
}
I know I know, what the heck-fire is CastIterator? Well, it's defined as such:
Code:
static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) {
foreach (object obj in source) yield return (TResult)obj;
}
Is this not the same as the original OP's code of:
Code:
For Each x As SearchResult In src
Just merely doing boxing (casting to Object) and unboxing (casting back to SearchResult)?
Perhaps the code may not work, however IDirectorySearch being there or not doesn't seem to matter. The class SearchResultCollection implements IEnumerable, which is more than enough to qualify it for Cast<T> and Cast<T> does a foreach on the SearchResultCollection (which is valid; IEnumerable is there as well as ICollection and if we really wanted to see, C# supports pattern matching for the foreach construct so we could even get away with not having IEnumerable [in special circumstances where GetEnumerator must exist and the return value of GetEnumerator must contain two properties: MoveNext() and Current; MoveNext() is a Boolean while Current returns an object]) which merely returns the object in a collection as they are pulled.
Following this, let's test the logic out, shall we?
Code:
var oSearcher = new System.DirectoryServices.DirectorySearcher();
var oResults = oSearcher.FindAll().Cast<System.DirectoryServices.SearchResult>();
foreach (System.DirectoryServices.SearchResult oResult in oResults)
Console.WriteLine(oResult.Path);
Console.ReadLine();
This code compiles and runs in VS2012 running on .NET 4.0, and in fact does loop through correctly.
EDIT: Here's a test class to throw into a foreach loop in C# (Does not work in VB.net, but since all the base .NET framework code is C#, this sample is valid for the sake of argument):
Code:
class Foo
{
public Bar GetEnumerator() { return new Bar(); }
public struct Bar
{
public bool MoveNext()
{
return false;
}
public object Current
{
get { return null; }
}
}
}
// The following will compile
var z = new Foo();
foreach (var item in z)
{
}
Last edited by formlesstree4; Mar 17th, 2014 at 06:00 PM.
Reason: Clarifying the pattern matching constraint
-
Mar 17th, 2014, 07:05 PM
#29
Re: How to use Paralell.ForEach with a SearchResultCollection
I didn't know about that Cast extension method but yeah that is better than my extension method in post #10 as it doesn't need to create a new list at all. So you're right, the simplest way would be something like this:
vb.net Code:
Private Sub Example()
Dim Searcher As New DirectorySearcher
Dim src As IEnumerable(Of SearchResult) = Searcher.FindAll().Cast(Of SearchResult)()
Parallel.ForEach(src, AddressOf test)
End Sub
Private Sub test(Result As SearchResult)
MessageBox.Show(Result.Path)
End Sub
or in line because its "less work" lol
vb.net Code:
Private Sub Example()
Dim Searcher As New DirectorySearcher
Dim src As IEnumerable(Of SearchResult) = Searcher.FindAll().Cast(Of SearchResult)()
Parallel.ForEach(src, Sub(Result As SearchResult)
MessageBox.Show(Result.Path)
End Sub)
End Sub
Thanks for the heads up on the Cast extension method - I'm sure that will come in handy in future
Last edited by chris128; Mar 17th, 2014 at 07:09 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|